]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branches 'fixes', 'misc', 'mmci', 'unstable/dma-for-next' and 'sa11x0' into...
authorRussell King <rmk+kernel@arm.linux.org.uk>
Wed, 23 Oct 2013 22:38:54 +0000 (23:38 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Wed, 23 Oct 2013 22:38:54 +0000 (23:38 +0100)
1087 files changed:
CREDITS
Documentation/DMA-API-HOWTO.txt
Documentation/DMA-API.txt
Documentation/arm64/tagged-pointers.txt
Documentation/block/00-INDEX
Documentation/block/cmdline-partition.txt
Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt
Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt [moved from Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt with 93% similarity]
Documentation/devicetree/bindings/mmc/tmio_mmc.txt
Documentation/devicetree/bindings/net/fsl-tsec-phy.txt
Documentation/devicetree/bindings/pci/designware-pcie.txt
Documentation/devicetree/bindings/serial/qca,ar9330-uart.txt [moved from Documentation/devicetree/bindings/tty/serial/qca,ar9330-uart.txt with 100% similarity]
Documentation/filesystems/vfs.txt
Documentation/kernel-parameters.txt
Documentation/networking/bonding.txt
Documentation/scheduler/sched-design-CFS.txt
Documentation/sound/alsa/HD-Audio-Models.txt
MAINTAINERS
Makefile
arch/Kconfig
arch/arc/include/asm/spinlock.h
arch/arc/include/asm/uaccess.h
arch/arc/kernel/signal.c
arch/arc/kernel/time.c
arch/arc/kernel/unaligned.c
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/am335x-bone-common.dtsi [new file with mode: 0644]
arch/arm/boot/dts/am335x-bone.dts
arch/arm/boot/dts/am335x-boneblack.dts [new file with mode: 0644]
arch/arm/boot/dts/armada-370-netgear-rn102.dts
arch/arm/boot/dts/armada-xp.dtsi
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/atlas6.dtsi
arch/arm/boot/dts/imx27.dtsi
arch/arm/boot/dts/imx51.dtsi
arch/arm/boot/dts/imx6q-pinfunc.h
arch/arm/boot/dts/kirkwood.dtsi
arch/arm/boot/dts/omap3-beagle-xm.dts
arch/arm/boot/dts/omap3-igep.dtsi
arch/arm/boot/dts/omap4-panda-common.dtsi
arch/arm/boot/dts/omap4-sdp.dts
arch/arm/boot/dts/omap5.dtsi
arch/arm/boot/dts/prima2.dtsi
arch/arm/boot/dts/r8a73a4.dtsi
arch/arm/boot/dts/r8a7778.dtsi
arch/arm/boot/dts/r8a7779.dtsi
arch/arm/boot/dts/r8a7790.dtsi
arch/arm/boot/dts/sh73a0.dtsi
arch/arm/common/Makefile
arch/arm/common/bL_switcher.c [new file with mode: 0644]
arch/arm/common/bL_switcher_dummy_if.c [new file with mode: 0644]
arch/arm/common/edma.c
arch/arm/common/mcpm_entry.c
arch/arm/common/mcpm_head.S
arch/arm/common/timer-sp.c
arch/arm/configs/h3600_defconfig
arch/arm/configs/multi_v7_defconfig
arch/arm/crypto/.gitignore [new file with mode: 0644]
arch/arm/crypto/Makefile
arch/arm/crypto/aes_glue.c
arch/arm/crypto/aes_glue.h [new file with mode: 0644]
arch/arm/crypto/aesbs-core.S_shipped [new file with mode: 0644]
arch/arm/crypto/aesbs-glue.c [new file with mode: 0644]
arch/arm/crypto/bsaes-armv7.pl [new file with mode: 0644]
arch/arm/include/asm/Kbuild
arch/arm/include/asm/atomic.h
arch/arm/include/asm/bL_switcher.h [new file with mode: 0644]
arch/arm/include/asm/cmpxchg.h
arch/arm/include/asm/cputype.h
arch/arm/include/asm/dma-mapping.h
arch/arm/include/asm/hardirq.h
arch/arm/include/asm/mach/arch.h
arch/arm/include/asm/mcpm.h
arch/arm/include/asm/memory.h
arch/arm/include/asm/pgtable-2level.h
arch/arm/include/asm/pgtable-3level.h
arch/arm/include/asm/processor.h
arch/arm/include/asm/smp.h
arch/arm/include/asm/spinlock.h
arch/arm/include/asm/spinlock_types.h
arch/arm/include/asm/tlbflush.h
arch/arm/include/asm/unified.h
arch/arm/include/debug/efm32.S [new file with mode: 0644]
arch/arm/include/uapi/asm/Kbuild
arch/arm/include/uapi/asm/perf_regs.h [new file with mode: 0644]
arch/arm/kernel/Makefile
arch/arm/kernel/armksyms.c
arch/arm/kernel/entry-header.S
arch/arm/kernel/head.S
arch/arm/kernel/perf_event.c
arch/arm/kernel/perf_regs.c [new file with mode: 0644]
arch/arm/kernel/setup.c
arch/arm/kernel/sleep.S
arch/arm/kernel/smp.c
arch/arm/kernel/smp_tlb.c
arch/arm/kernel/suspend.c
arch/arm/kvm/reset.c
arch/arm/lib/bitops.h
arch/arm/lib/uaccess_with_memcpy.c
arch/arm/mach-at91/at91rm9200_time.c
arch/arm/mach-at91/at91sam926x_time.c
arch/arm/mach-at91/at91sam9g45_reset.S
arch/arm/mach-at91/at91x40_time.c
arch/arm/mach-davinci/board-dm365-evm.c
arch/arm/mach-davinci/include/mach/serial.h
arch/arm/mach-imx/clk-fixup-mux.c
arch/arm/mach-imx/clk-imx27.c
arch/arm/mach-imx/clk-imx51-imx53.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-imx/system.c
arch/arm/mach-integrator/pci_v3.h
arch/arm/mach-mvebu/coherency.c
arch/arm/mach-mvebu/pmsu.c
arch/arm/mach-mvebu/system-controller.c
arch/arm/mach-omap2/cclock44xx_data.c
arch/arm/mach-omap2/cpuidle44xx.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/mux34xx.c
arch/arm/mach-omap2/omap-smp.c
arch/arm/mach-omap2/omap_device.c
arch/arm/mach-sa1100/assabet.c
arch/arm/mach-sa1100/collie.c
arch/arm/mach-sa1100/include/mach/gpio.h [deleted file]
arch/arm/mach-sa1100/include/mach/h3xxx.h
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/board-lager.c
arch/arm/mach-shmobile/clock-r8a73a4.c
arch/arm/mach-shmobile/clock-sh73a0.c
arch/arm/mach-u300/Kconfig
arch/arm/mach-ux500/cache-l2x0.c
arch/arm/mach-vexpress/tc2_pm.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/idmap.c
arch/arm/mm/init.c
arch/arm/mm/mm.h
arch/arm/mm/mmap.c
arch/arm/mm/mmu.c
arch/arm64/Kconfig.debug
arch/arm64/configs/defconfig
arch/arm64/include/asm/hwcap.h
arch/arm64/include/asm/uaccess.h
arch/arm64/kernel/fpsimd.c
arch/arm64/kernel/process.c
arch/arm64/kernel/setup.c
arch/arm64/mm/fault.c
arch/arm64/mm/tlb.S
arch/avr32/include/asm/Kbuild
arch/avr32/include/asm/cputime.h [deleted file]
arch/avr32/include/asm/delay.h [deleted file]
arch/avr32/include/asm/device.h [deleted file]
arch/avr32/include/asm/div64.h [deleted file]
arch/avr32/include/asm/emergency-restart.h [deleted file]
arch/avr32/include/asm/futex.h [deleted file]
arch/avr32/include/asm/irq_regs.h [deleted file]
arch/avr32/include/asm/local.h [deleted file]
arch/avr32/include/asm/local64.h [deleted file]
arch/avr32/include/asm/percpu.h [deleted file]
arch/avr32/include/asm/scatterlist.h [deleted file]
arch/avr32/include/asm/sections.h [deleted file]
arch/avr32/include/asm/topology.h [deleted file]
arch/avr32/include/asm/xor.h [deleted file]
arch/avr32/kernel/process.c
arch/avr32/kernel/time.c
arch/mips/Makefile
arch/mips/alchemy/board-mtx1.c
arch/mips/alchemy/common/usb.c
arch/mips/bcm63xx/cpu.c
arch/mips/boot/dts/include/dt-bindings
arch/mips/cavium-octeon/csrc-octeon.c
arch/mips/dec/prom/init.c
arch/mips/include/asm/cpu-features.h
arch/mips/include/asm/cpu-info.h
arch/mips/include/asm/cpu-type.h [new file with mode: 0644]
arch/mips/include/asm/cpu.h
arch/mips/include/asm/mach-au1x00/au1000.h
arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h
arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h
arch/mips/include/asm/mach-ip28/cpu-feature-overrides.h
arch/mips/include/asm/mipsregs.h
arch/mips/include/asm/pci.h
arch/mips/include/asm/timex.h
arch/mips/include/asm/vga.h
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/idle.c
arch/mips/kernel/time.c
arch/mips/kernel/traps.c
arch/mips/mm/c-octeon.c
arch/mips/mm/c-r4k.c
arch/mips/mm/dma-default.c
arch/mips/mm/page.c
arch/mips/mm/sc-mips.c
arch/mips/mm/tlb-r4k.c
arch/mips/mm/tlbex.c
arch/mips/mti-malta/malta-time.c
arch/mips/mti-sead3/sead3-time.c
arch/mips/netlogic/xlr/fmn-config.c
arch/mips/oprofile/common.c
arch/mips/pci/pci-bcm1480.c
arch/mips/sibyte/bcm1480/setup.c
arch/mips/sibyte/sb1250/setup.c
arch/mips/sni/setup.c
arch/openrisc/include/asm/prom.h
arch/parisc/mm/fault.c
arch/powerpc/boot/Makefile
arch/powerpc/boot/epapr-wrapper.c [new file with mode: 0644]
arch/powerpc/boot/epapr.c
arch/powerpc/boot/of.c
arch/powerpc/boot/wrapper
arch/powerpc/include/asm/irq.h
arch/powerpc/include/asm/processor.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/iommu.c
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/misc_64.S
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/sysfs.c
arch/powerpc/kernel/tm.S
arch/powerpc/kernel/vio.c
arch/powerpc/lib/checksum_64.S
arch/powerpc/lib/sstep.c
arch/powerpc/mm/init_64.c
arch/powerpc/mm/mem.c
arch/powerpc/perf/power8-pmu.c
arch/powerpc/platforms/pseries/smp.c
arch/s390/Kconfig
arch/s390/include/asm/mutex.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/spinlock.h
arch/score/Kconfig
arch/score/Makefile
arch/score/include/asm/checksum.h
arch/score/include/asm/io.h
arch/score/include/asm/pgalloc.h
arch/score/kernel/entry.S
arch/score/kernel/process.c
arch/sparc/Kconfig
arch/sparc/include/asm/floppy_64.h
arch/sparc/kernel/Makefile
arch/sparc/kernel/ds.c
arch/sparc/kernel/ldc.c
arch/tile/Kconfig
arch/tile/gxio/iorpc_mpipe.c
arch/tile/gxio/iorpc_mpipe_info.c
arch/tile/gxio/iorpc_trio.c
arch/tile/gxio/iorpc_usb_host.c
arch/tile/gxio/usb_host.c
arch/tile/include/arch/mpipe.h
arch/tile/include/arch/mpipe_constants.h
arch/tile/include/arch/mpipe_shm.h
arch/tile/include/arch/trio_constants.h
arch/tile/include/asm/page.h
arch/tile/include/asm/pgtable_32.h
arch/tile/include/asm/pgtable_64.h
arch/tile/include/gxio/iorpc_mpipe.h
arch/tile/include/gxio/iorpc_mpipe_info.h
arch/tile/include/gxio/iorpc_trio.h
arch/tile/include/gxio/iorpc_usb_host.h
arch/tile/include/gxio/usb_host.h
arch/tile/kernel/compat.c
arch/tile/kernel/futex_64.S [deleted file]
arch/tile/kernel/setup.c
arch/tile/kernel/unaligned.c
arch/tile/mm/fault.c
arch/tile/mm/init.c
arch/tile/mm/pgtable.c
arch/x86/Kconfig
arch/x86/include/asm/xen/page.h
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_intel_ds.c
arch/x86/kernel/cpu/perf_event_intel_uncore.c
arch/x86/kernel/entry_64.S
arch/x86/kernel/microcode_amd.c
arch/x86/kernel/reboot.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/sysfb_simplefb.c
arch/x86/kvm/emulate.c
arch/x86/kvm/paging_tmpl.h
arch/x86/kvm/vmx.c
arch/x86/pci/mmconfig-shared.c
arch/x86/platform/efi/efi.c
arch/x86/xen/p2m.c
arch/x86/xen/spinlock.c
block/Kconfig
block/Makefile
block/blk-cgroup.c
block/blk-core.c
block/blk-exec.c
block/blk-settings.c
block/cfq-iosched.c
block/deadline-iosched.c
block/elevator.c
block/genhd.c
block/partitions/Kconfig
block/partitions/cmdline.c
crypto/Kconfig
drivers/acpi/acpi_ipmi.c
drivers/acpi/scan.c
drivers/amba/bus.c
drivers/ata/pata_ixp4xx_cf.c
drivers/ata/pata_octeon_cf.c
drivers/ata/sata_promise.c
drivers/atm/he.c
drivers/atm/nicstar.c
drivers/base/core.c
drivers/bcma/driver_pci.c
drivers/bcma/scan.c
drivers/block/cciss.c
drivers/block/cpqarray.c
drivers/block/nvme-core.c
drivers/block/rbd.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/bus/mvebu-mbus.c
drivers/char/tpm/xen-tpmfront.c
drivers/clocksource/Kconfig
drivers/clocksource/clksrc-of.c
drivers/clocksource/em_sti.c
drivers/clocksource/exynos_mct.c
drivers/cpufreq/acpi-cpufreq.c
drivers/cpufreq/cpufreq-cpu0.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/exynos5440-cpufreq.c
drivers/cpufreq/imx6q-cpufreq.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/spear-cpufreq.c
drivers/crypto/ixp4xx_crypto.c
drivers/dma/Kconfig
drivers/dma/amba-pl08x.c
drivers/dma/dw/platform.c
drivers/dma/edma.c
drivers/dma/imx-dma.c
drivers/dma/imx-sdma.c
drivers/dma/pl330.c
drivers/firmware/dcdbas.c
drivers/firmware/google/gsmi.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-rcar.c
drivers/gpio/gpio-sa1100.c
drivers/gpu/drm/ast/ast_drv.h
drivers/gpu/drm/drm_context.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_fops.c
drivers/gpu/drm/drm_stub.c
drivers/gpu/drm/exynos/Kconfig
drivers/gpu/drm/exynos/exynos_drm_buf.c
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/i2c/tda998x_drv.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dvo.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_tv.c
drivers/gpu/drm/msm/adreno/adreno_gpu.c
drivers/gpu/drm/msm/mdp4/mdp4_kms.c
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_drv.h
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/msm/msm_gem.h
drivers/gpu/drm/msm/msm_gem_submit.c
drivers/gpu/drm/msm/msm_gpu.c
drivers/gpu/drm/nouveau/core/subdev/bios/init.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_sgdma.c
drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/btc_dpm.c
drivers/gpu/drm/radeon/btc_dpm.h
drivers/gpu/drm/radeon/ci_dpm.c
drivers/gpu/drm/radeon/ci_smc.c
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/cypress_dpm.c
drivers/gpu/drm/radeon/dce6_afmt.c
drivers/gpu/drm/radeon/kv_dpm.c
drivers/gpu/drm/radeon/kv_dpm.h
drivers/gpu/drm/radeon/kv_smc.c
drivers/gpu/drm/radeon/ni_dpm.c
drivers/gpu/drm/radeon/ppsmc.h
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_dpm.c
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/radeon_trace.h
drivers/gpu/drm/radeon/radeon_uvd.c
drivers/gpu/drm/radeon/rs400.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rs780_dpm.c
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/radeon/rv6xx_dpm.c
drivers/gpu/drm/radeon/rv770_dpm.c
drivers/gpu/drm/radeon/rv770_smc.c
drivers/gpu/drm/radeon/rv770_smc.h
drivers/gpu/drm/radeon/rv770d.h
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/si_dpm.c
drivers/gpu/drm/radeon/si_smc.c
drivers/gpu/drm/radeon/sumo_dpm.c
drivers/gpu/drm/radeon/trinity_dpm.c
drivers/gpu/drm/radeon/trinity_dpm.h
drivers/gpu/drm/radeon/trinity_smc.c
drivers/gpu/drm/radeon/uvd_v1_0.c
drivers/gpu/drm/ttm/ttm_object.c
drivers/gpu/drm/ttm/ttm_tt.c
drivers/gpu/drm/udl/udl_gem.c
drivers/hid/hid-core.c
drivers/hid/hid-input.c
drivers/hid/hid-lenovo-tpkbd.c
drivers/hid/hid-lg2ff.c
drivers/hid/hid-lg3ff.c
drivers/hid/hid-lg4ff.c
drivers/hid/hid-lgff.c
drivers/hid/hid-logitech-dj.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-sony.c
drivers/hid/hid-steelseries.c
drivers/hid/hid-zpff.c
drivers/hv/connection.c
drivers/hv/hv_kvp.c
drivers/hv/hv_snapshot.c
drivers/hv/hv_util.c
drivers/hwmon/applesmc.c
drivers/i2c/busses/i2c-designware-core.c
drivers/i2c/busses/i2c-ismt.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/iio/accel/bma180.c
drivers/iio/adc/at91_adc.c
drivers/iio/amplifiers/ad8366.c
drivers/iio/buffer_cb.c
drivers/iio/dac/mcp4725.c
drivers/iio/iio_core.h
drivers/iio/industrialio-buffer.c
drivers/iio/industrialio-core.c
drivers/iio/industrialio-event.c
drivers/iio/magnetometer/st_magn_core.c
drivers/iio/temperature/tmp006.c
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/iommu/arm-smmu.c
drivers/irqchip/irq-gic.c
drivers/isdn/hardware/mISDN/hfcpci.c
drivers/isdn/hisax/amd7930_fn.c
drivers/isdn/hisax/avm_pci.c
drivers/isdn/hisax/config.c
drivers/isdn/hisax/diva.c
drivers/isdn/hisax/elsa.c
drivers/isdn/hisax/elsa_ser.c
drivers/isdn/hisax/hfc_pci.c
drivers/isdn/hisax/hfc_sx.c
drivers/isdn/hisax/hscx_irq.c
drivers/isdn/hisax/icc.c
drivers/isdn/hisax/ipacx.c
drivers/isdn/hisax/isac.c
drivers/isdn/hisax/isar.c
drivers/isdn/hisax/jade.c
drivers/isdn/hisax/jade_irq.c
drivers/isdn/hisax/l3_1tr6.c
drivers/isdn/hisax/netjet.c
drivers/isdn/hisax/q931.c
drivers/isdn/hisax/w6692.c
drivers/mailbox/mailbox-omap2.c
drivers/md/bcache/bcache.h
drivers/md/bcache/bset.c
drivers/md/bcache/btree.c
drivers/md/bcache/journal.c
drivers/md/bcache/request.c
drivers/md/bcache/sysfs.c
drivers/md/bcache/util.c
drivers/md/bcache/util.h
drivers/md/bcache/writeback.c
drivers/md/dm-io.c
drivers/md/dm-mpath.c
drivers/md/dm-snap-persistent.c
drivers/md/dm-snap.c
drivers/md/dm-stats.c
drivers/md/dm-thin.c
drivers/md/dm.c
drivers/md/dm.h
drivers/media/platform/omap3isp/isp.c
drivers/media/platform/omap3isp/isp.h
drivers/misc/mei/amthif.c
drivers/misc/mei/bus.c
drivers/misc/mei/client.h
drivers/misc/mei/hbm.c
drivers/misc/mei/init.c
drivers/misc/mei/main.c
drivers/misc/mei/mei_dev.h
drivers/mmc/card/queue.c
drivers/mmc/host/mmci.c
drivers/mmc/host/mmci.h
drivers/mmc/host/sdhci-acpi.c
drivers/mmc/host/sh_mobile_sdhi.c
drivers/mtd/nand/pxa3xx_nand.c
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_alb.h
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_sysfs.c
drivers/net/bonding/bonding.h
drivers/net/can/flexcan.c
drivers/net/can/slcan.c
drivers/net/can/usb/peak_usb/pcan_usb_core.c
drivers/net/ethernet/adi/bfin_mac.c
drivers/net/ethernet/amd/sun3lance.c
drivers/net/ethernet/atheros/alx/main.c
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/bgmac.c
drivers/net/ethernet/broadcom/bgmac.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
drivers/net/ethernet/broadcom/cnic.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/broadcom/tg3.h
drivers/net/ethernet/brocade/bna/bnad.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/dec/tulip/de4x5.c
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_cmds.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/gianfar_ptp.c
drivers/net/ethernet/hp/hp100.c
drivers/net/ethernet/ibm/ehea/ehea_main.c
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/intel/e1000e/ethtool.c
drivers/net/ethernet/intel/e1000e/ich8lan.c
drivers/net/ethernet/intel/e1000e/ich8lan.h
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/i40e/i40e_adminq.c
drivers/net/ethernet/intel/i40e/i40e_common.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/igb/e1000_82575.c
drivers/net/ethernet/intel/igb/e1000_mac.c
drivers/net/ethernet/intel/igb/igb_ethtool.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igbvf/netdev.c
drivers/net/ethernet/intel/ixgb/ixgb_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/lantiq_etop.c
drivers/net/ethernet/marvell/pxa168_eth.c
drivers/net/ethernet/marvell/skge.c
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
drivers/net/ethernet/micrel/ks8851_mll.c
drivers/net/ethernet/moxa/moxart_ether.c
drivers/net/ethernet/natsemi/jazzsonic.c
drivers/net/ethernet/natsemi/xtsonic.c
drivers/net/ethernet/nxp/lpc_eth.c
drivers/net/ethernet/octeon/octeon_mgmt.c
drivers/net/ethernet/pasemi/pasemi_mac.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
drivers/net/ethernet/qlogic/qlge/qlge_mpi.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/sfc/Kconfig
drivers/net/ethernet/sfc/ef10.c
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/mcdi.c
drivers/net/ethernet/sfc/mcdi_port.c
drivers/net/ethernet/sfc/nic.h
drivers/net/ethernet/smsc/smc91x.h
drivers/net/ethernet/smsc/smsc9420.c
drivers/net/ethernet/toshiba/ps3_gelic_net.c
drivers/net/ethernet/via/via-rhine.c
drivers/net/ethernet/xilinx/ll_temac_main.c
drivers/net/irda/mcs7780.c
drivers/net/loopback.c
drivers/net/netconsole.c
drivers/net/phy/cicada.c
drivers/net/ppp/pptp.c
drivers/net/slip/slip.c
drivers/net/tun.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/dm9601.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/usbnet.c
drivers/net/vxlan.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/b43/dma.c
drivers/net/wireless/b43legacy/dma.c
drivers/net/wireless/brcm80211/Kconfig
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
drivers/net/wireless/brcm80211/brcmfmac/usb.c
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
drivers/net/wireless/cw1200/cw1200_spi.c
drivers/net/wireless/mwifiex/11n_aggr.c
drivers/net/wireless/mwifiex/11n_aggr.h
drivers/net/wireless/mwifiex/cmdevt.c
drivers/net/wireless/mwifiex/usb.c
drivers/net/wireless/mwifiex/wmm.c
drivers/net/wireless/p54/p54usb.c
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rtl818x/rtl8187/dev.c
drivers/net/wireless/rtlwifi/wifi.h
drivers/net/xen-netback/common.h
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/netback.c
drivers/net/xen-netback/xenbus.c
drivers/of/platform.c
drivers/parport/parport_pc.c
drivers/pci/pci-acpi.c
drivers/pci/pci.c
drivers/pinctrl/pinconf.c
drivers/pinctrl/pinctrl-exynos.c
drivers/pinctrl/pinctrl-palmas.c
drivers/pinctrl/pinctrl-tegra114.c
drivers/regulator/da9063-regulator.c
drivers/regulator/palmas-regulator.c
drivers/regulator/ti-abb-regulator.c
drivers/regulator/wm831x-ldo.c
drivers/regulator/wm8350-regulator.c
drivers/scsi/bnx2fc/bnx2fc.h
drivers/scsi/bnx2fc/bnx2fc_hwi.c
drivers/scsi/bnx2i/bnx2i.h
drivers/scsi/bnx2i/bnx2i_hwi.c
drivers/scsi/scsi_lib.c
drivers/staging/comedi/Kconfig
drivers/staging/comedi/drivers/ni_65xx.c
drivers/staging/dgap/dgap_driver.c
drivers/staging/dgnc/dgnc_driver.c
drivers/staging/dwc2/platform.c
drivers/staging/et131x/et131x.c
drivers/staging/iio/Kconfig
drivers/staging/iio/light/isl29018.c
drivers/staging/iio/magnetometer/hmc5843.c
drivers/staging/iio/meter/ade7854-spi.c
drivers/staging/imx-drm/imx-drm-core.c
drivers/staging/imx-drm/ipuv3-crtc.c
drivers/staging/line6/toneport.c
drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c
drivers/staging/lustre/lustre/Kconfig
drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
drivers/staging/lustre/lustre/libcfs/workitem.c
drivers/staging/lustre/lustre/obdecho/echo_client.c
drivers/staging/lustre/lustre/ptlrpc/pinger.c
drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
drivers/staging/lustre/lustre/ptlrpc/service.c
drivers/staging/media/dt3155v4l/dt3155v4l.c
drivers/staging/octeon-usb/cvmx-usb.c
drivers/staging/octeon/ethernet-mem.c
drivers/staging/octeon/ethernet-rgmii.c
drivers/staging/octeon/ethernet-rx.c
drivers/staging/rtl8188eu/core/rtw_ieee80211.c
drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
drivers/staging/rtl8188eu/core/rtw_mp.c
drivers/staging/rtl8188eu/core/rtw_wlan_util.c
drivers/staging/rtl8188eu/hal/rtl8188e_dm.c
drivers/staging/rtl8188eu/include/odm.h
drivers/staging/rtl8188eu/include/rtl8188e_hal.h
drivers/staging/rtl8188eu/include/rtw_mlme_ext.h
drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
drivers/staging/rtl8188eu/os_dep/usb_intf.c
drivers/staging/rtl8192u/r819xU_cmdpkt.c
drivers/staging/vt6656/card.c
drivers/staging/vt6656/iwctl.c
drivers/staging/vt6656/main_usb.c
drivers/staging/vt6656/rxtx.c
drivers/staging/xillybus/xillybus_core.c
drivers/staging/zram/zram_drv.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_nego.c
drivers/target/iscsi/iscsi_target_util.c
drivers/target/target_core_sbc.c
drivers/target/target_core_transport.c
drivers/target/target_core_xcopy.c
drivers/tty/hvc/hvc_xen.c
drivers/tty/n_tty.c
drivers/tty/serial/pch_uart.c
drivers/tty/serial/serial-tegra.c
drivers/tty/tty_io.c
drivers/tty/tty_ioctl.c
drivers/usb/chipidea/Kconfig
drivers/usb/chipidea/ci_hdrc_imx.c
drivers/usb/chipidea/ci_hdrc_pci.c
drivers/usb/chipidea/core.c
drivers/usb/chipidea/udc.c
drivers/usb/core/devio.c
drivers/usb/core/hub.c
drivers/usb/dwc3/Kconfig
drivers/usb/dwc3/dwc3-exynos.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/cdc2.c
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/f_ecm.c
drivers/usb/gadget/f_eem.c
drivers/usb/gadget/f_fs.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/gadget/fotg210-udc.c
drivers/usb/gadget/fusb300_udc.c
drivers/usb/gadget/lpc32xx_udc.c
drivers/usb/gadget/multi.c
drivers/usb/gadget/mv_u3d_core.c
drivers/usb/gadget/pxa25x_udc.c
drivers/usb/gadget/s3c-hsotg.c
drivers/usb/host/bcma-hcd.c
drivers/usb/host/ehci-atmel.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-grlib.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-mv.c
drivers/usb/host/ehci-octeon.c
drivers/usb/host/ehci-omap.c
drivers/usb/host/ehci-orion.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-platform.c
drivers/usb/host/ehci-pmcmsp.c
drivers/usb/host/ehci-ppc-of.c
drivers/usb/host/ehci-ps3.c
drivers/usb/host/ehci-q.c
drivers/usb/host/ehci-s5p.c
drivers/usb/host/ehci-sead3.c
drivers/usb/host/ehci-sh.c
drivers/usb/host/ehci-spear.c
drivers/usb/host/ehci-tegra.c
drivers/usb/host/ehci-tilegx.c
drivers/usb/host/ehci-w90x900.c
drivers/usb/host/ehci-xilinx-of.c
drivers/usb/host/fsl-mph-dr-of.c
drivers/usb/host/imx21-hcd.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-exynos.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-nxp.c
drivers/usb/host/ohci-octeon.c
drivers/usb/host/ohci-omap3.c
drivers/usb/host/ohci-pxa27x.c
drivers/usb/host/ohci-q.c
drivers/usb/host/ohci-sa1111.c
drivers/usb/host/ohci-spear.c
drivers/usb/host/ssb-hcd.c
drivers/usb/host/uhci-pci.c
drivers/usb/host/uhci-platform.c
drivers/usb/host/uhci-q.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/musb/am35x.c
drivers/usb/musb/da8xx.c
drivers/usb/musb/davinci.c
drivers/usb/musb/musb_dsps.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/tusb6010.c
drivers/usb/phy/phy-gpio-vbus-usb.c
drivers/usb/phy/phy-omap-usb3.c
drivers/usb/serial/Kconfig
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/vhost/scsi.c
drivers/vhost/vhost.c
drivers/video/amba-clcd.c
drivers/video/mmp/hw/mmp_ctrl.c
drivers/video/mxsfb.c
drivers/video/neofb.c
drivers/video/of_display_timing.c
drivers/video/omap2/displays-new/Kconfig
drivers/video/omap2/displays-new/connector-analog-tv.c
drivers/video/omap2/displays-new/connector-dvi.c
drivers/video/omap2/displays-new/connector-hdmi.c
drivers/video/omap2/dss/dispc.c
drivers/video/s3fb.c
drivers/xen/balloon.c
fs/9p/v9fs.c
fs/9p/vfs_inode_dotl.c
fs/afs/dir.c
fs/aio.c
fs/autofs4/waitq.c
fs/binfmt_elf.c
fs/bio-integrity.c
fs/bio.c
fs/btrfs/async-thread.c
fs/btrfs/async-thread.h
fs/btrfs/btrfs_inode.h
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/dev-replace.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/free-space-cache.h
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/ordered-data.c
fs/btrfs/ordered-data.h
fs/btrfs/relocation.c
fs/btrfs/scrub.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/cachefiles/namei.c
fs/cachefiles/xattr.c
fs/cifs/cifsfs.h
fs/cifs/cifsglob.h
fs/cifs/cifspdu.h
fs/cifs/cifssmb.c
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/fscache.c
fs/cifs/fscache.h
fs/cifs/inode.c
fs/cifs/readdir.c
fs/cifs/sess.c
fs/fscache/cookie.c
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/gfs2/inode.c
fs/namei.c
fs/nfs/dir.c
fs/nfs/nfs4file.c
fs/nfs/nfs4filelayoutdev.c
fs/nfs/nfs4proc.c
fs/nilfs2/page.c
fs/nilfs2/segment.c
fs/ocfs2/dcache.c
fs/ocfs2/super.c
fs/open.c
fs/pstore/platform.c
fs/reiserfs/journal.c
fs/super.c
fs/sysv/super.c
fs/udf/ialloc.c
fs/udf/super.c
fs/udf/udf_sb.h
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_da_btree.c
fs/xfs/xfs_dir2_block.c
fs/xfs/xfs_dir2_format.h
fs/xfs/xfs_dir2_readdir.c
fs/xfs/xfs_dir2_sf.c
fs/xfs/xfs_dquot.c
fs/xfs/xfs_fs.h
fs/xfs/xfs_icache.c
fs/xfs/xfs_log_recover.c
include/asm-generic/hugetlb.h
include/asm-generic/vtime.h
include/drm/drmP.h
include/drm/drm_pciids.h
include/linux/amba/bus.h
include/linux/balloon_compaction.h
include/linux/bcma/bcma_driver_pci.h
include/linux/blkdev.h
include/linux/ceph/osd_client.h
include/linux/device-mapper.h
include/linux/dma-mapping.h
include/linux/hid.h
include/linux/hyperv.h
include/linux/intel-iommu.h
include/linux/irqchip/arm-gic.h
include/linux/kernel.h
include/linux/kvm_host.h
include/linux/memcontrol.h
include/linux/mutex.h
include/linux/netdevice.h
include/linux/netfilter/ipset/ip_set.h
include/linux/nfs_xdr.h
include/linux/of_irq.h
include/linux/regulator/driver.h
include/linux/skbuff.h
include/linux/smp.h
include/linux/timex.h
include/linux/usb/usbnet.h
include/net/addrconf.h
include/net/bluetooth/hci.h
include/net/ip.h
include/net/ip_vs.h
include/net/mrp.h
include/net/net_namespace.h
include/net/netfilter/nf_conntrack_extend.h
include/net/netfilter/nf_conntrack_synproxy.h
include/net/secure_seq.h
include/net/sock.h
include/trace/events/block.h
include/trace/events/btrfs.h
include/trace/events/power_cpu_migrate.h [new file with mode: 0644]
include/uapi/drm/radeon_drm.h
include/uapi/linux/perf_event.h
ipc/msg.c
ipc/sem.c
ipc/shm.c
ipc/util.c
ipc/util.h
kernel/audit.c
kernel/context_tracking.c
kernel/events/core.c
kernel/kmod.c
kernel/params.c
kernel/pid.c
kernel/power/snapshot.c
kernel/power/user.c
kernel/reboot.c
kernel/sched/debug.c
kernel/sched/fair.c
kernel/sched/stats.h
kernel/softirq.c
kernel/time/ntp.c
kernel/time/timekeeping.c
kernel/watchdog.c
lib/hexdump.c
lib/kobject.c
lib/lockref.c
mm/Kconfig
mm/bounce.c
mm/compaction.c
mm/hwpoison-inject.c
mm/madvise.c
mm/memcontrol.c
mm/memory-failure.c
mm/migrate.c
mm/mlock.c
mm/page_alloc.c
mm/vmscan.c
net/802/mrp.c
net/batman-adv/soft-interface.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/l2cap_core.c
net/bluetooth/rfcomm/tty.c
net/bridge/br_netlink.c
net/bridge/br_private.h
net/bridge/br_stp.c
net/bridge/br_stp_if.c
net/ceph/osd_client.c
net/core/dev.c
net/core/flow_dissector.c
net/core/netpoll.c
net/core/secure_seq.c
net/dccp/ipv6.c
net/ipv4/af_inet.c
net/ipv4/igmp.c
net/ipv4/inetpeer.c
net/ipv4/ip_output.c
net/ipv4/ip_tunnel.c
net/ipv4/ip_tunnel_core.c
net/ipv4/ipmr.c
net/ipv4/netfilter/ipt_SYNPROXY.c
net/ipv4/raw.c
net/ipv4/tcp_metrics.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/ipv4/xfrm4_mode_tunnel.c
net/ipv6/addrconf.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/mcast.c
net/ipv6/netfilter/ip6t_SYNPROXY.c
net/ipv6/netfilter/nf_nat_proto_icmpv6.c
net/ipv6/raw.c
net/ipv6/sit.c
net/ipv6/udp.c
net/lapb/lapb_timer.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipset/ip_set_getport.c
net/netfilter/ipset/ip_set_hash_gen.h
net/netfilter/ipset/ip_set_hash_ipportnet.c
net/netfilter/ipset/ip_set_hash_net.c
net/netfilter/ipset/ip_set_hash_netiface.c
net/netfilter/ipset/ip_set_hash_netport.c
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/ipvs/ip_vs_est.c
net/netfilter/ipvs/ip_vs_lblc.c
net/netfilter/ipvs/ip_vs_lblcr.c
net/netfilter/ipvs/ip_vs_nq.c
net/netfilter/ipvs/ip_vs_sed.c
net/netfilter/ipvs/ip_vs_wlc.c
net/netfilter/ipvs/ip_vs_xmit.c
net/netfilter/nf_synproxy_core.c
net/netfilter/nfnetlink_queue_core.c
net/sched/sch_fq.c
net/sctp/input.c
net/sctp/ipv6.c
net/sunrpc/auth_gss/auth_gss.c
net/sysctl_net.c
scripts/checkpatch.pl
security/apparmor/crypto.c
security/apparmor/include/policy.h
security/apparmor/policy.c
security/selinux/avc.c
security/selinux/hooks.c
security/selinux/include/avc.h
sound/arm/pxa2xx-pcm.c
sound/core/compress_offload.c
sound/pci/ac97/ac97_codec.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/soc/atmel/atmel-pcm.c
sound/soc/blackfin/bf5xx-ac97-pcm.c
sound/soc/blackfin/bf5xx-i2s-pcm.c
sound/soc/blackfin/bf6xx-i2s.c
sound/soc/codecs/88pm860x-codec.c
sound/soc/codecs/ab8500-codec.c
sound/soc/codecs/max98095.c
sound/soc/davinci/davinci-pcm.c
sound/soc/fsl/fsl_dma.c
sound/soc/fsl/imx-pcm-fiq.c
sound/soc/fsl/imx-sgtl5000.c
sound/soc/fsl/mpc5200_dma.c
sound/soc/jz4740/jz4740-pcm.c
sound/soc/kirkwood/kirkwood-dma.c
sound/soc/nuc900/nuc900-pcm.c
sound/soc/omap/omap-pcm.c
sound/soc/pxa/pxa2xx-pcm.c
sound/soc/s6000/s6000-pcm.c
sound/soc/samsung/dma.c
sound/soc/samsung/idma.c
sound/soc/soc-core.c
tools/lib/lk/debugfs.c
tools/perf/arch/arm/Makefile
tools/perf/arch/arm/include/perf_regs.h [new file with mode: 0644]
tools/perf/arch/arm/util/unwind.c [new file with mode: 0644]
tools/perf/arch/x86/util/tsc.c
tools/perf/builtin-inject.c
tools/perf/builtin-kmem.c
tools/perf/builtin-report.c
tools/perf/builtin-script.c
tools/perf/builtin-trace.c
tools/perf/config/Makefile
tools/perf/config/feature-tests.mak
tools/perf/util/annotate.c
tools/perf/util/dwarf-aux.c
tools/perf/util/dwarf-aux.h
tools/perf/util/header.c
tools/perf/util/hist.c
tools/perf/util/machine.c
tools/perf/util/probe-finder.c
tools/perf/util/probe-finder.h
tools/perf/util/session.c
tools/perf/util/session.h
tools/perf/util/symbol-elf.c
tools/perf/util/trace-event-parse.c
tools/perf/util/unwind.c
virt/kvm/async_pf.c
virt/kvm/kvm_main.c

diff --git a/CREDITS b/CREDITS
index 9416a9a8b95e6c4404c80ade376feff7b6df406a..0640e16504832e43c2d3b9bb82b6b5fe3f5bea48 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -2808,8 +2808,7 @@ S: Ottawa, Ontario
 S: Canada K2P 0X8
 
 N: Mikael Pettersson
-E: mikpe@it.uu.se
-W: http://user.it.uu.se/~mikpe/linux/
+E: mikpelinux@gmail.com
 D: Miscellaneous fixes
 
 N: Reed H. Petty
index 14129f149a75432589f3bc925f7776a59354ef62..5e983031cc11be35fba1aab90546db5a7de1eeb3 100644 (file)
@@ -101,14 +101,23 @@ style to do this even if your device holds the default setting,
 because this shows that you did think about these issues wrt. your
 device.
 
-The query is performed via a call to dma_set_mask():
+The query is performed via a call to dma_set_mask_and_coherent():
 
-       int dma_set_mask(struct device *dev, u64 mask);
+       int dma_set_mask_and_coherent(struct device *dev, u64 mask);
 
-The query for consistent allocations is performed via a call to
-dma_set_coherent_mask():
+which will query the mask for both streaming and coherent APIs together.
+If you have some special requirements, then the following two separate
+queries can be used instead:
 
-       int dma_set_coherent_mask(struct device *dev, u64 mask);
+       The query for streaming mappings is performed via a call to
+       dma_set_mask():
+
+               int dma_set_mask(struct device *dev, u64 mask);
+
+       The query for consistent allocations is performed via a call
+       to dma_set_coherent_mask():
+
+               int dma_set_coherent_mask(struct device *dev, u64 mask);
 
 Here, dev is a pointer to the device struct of your device, and mask
 is a bit mask describing which bits of an address your device
@@ -137,7 +146,7 @@ exactly why.
 
 The standard 32-bit addressing device would do something like this:
 
-       if (dma_set_mask(dev, DMA_BIT_MASK(32))) {
+       if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) {
                printk(KERN_WARNING
                       "mydev: No suitable DMA available.\n");
                goto ignore_this_device;
@@ -171,22 +180,20 @@ the case would look like this:
 
        int using_dac, consistent_using_dac;
 
-       if (!dma_set_mask(dev, DMA_BIT_MASK(64))) {
+       if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) {
                using_dac = 1;
                consistent_using_dac = 1;
-               dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
-       } else if (!dma_set_mask(dev, DMA_BIT_MASK(32))) {
+       } else if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) {
                using_dac = 0;
                consistent_using_dac = 0;
-               dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
        } else {
                printk(KERN_WARNING
                       "mydev: No suitable DMA available.\n");
                goto ignore_this_device;
        }
 
-dma_set_coherent_mask() will always be able to set the same or a
-smaller mask as dma_set_mask(). However for the rare case that a
+The coherent coherent mask will always be able to set the same or a
+smaller mask as the streaming mask. However for the rare case that a
 device driver only uses consistent allocations, one would have to
 check the return value from dma_set_coherent_mask().
 
@@ -199,9 +206,9 @@ address you might do something like:
                goto ignore_this_device;
        }
 
-When dma_set_mask() is successful, and returns zero, the kernel saves
-away this mask you have provided.  The kernel will use this
-information later when you make DMA mappings.
+When dma_set_mask() or dma_set_mask_and_coherent() is successful, and
+returns zero, the kernel saves away this mask you have provided.  The
+kernel will use this information later when you make DMA mappings.
 
 There is a case which we are aware of at this time, which is worth
 mentioning in this documentation.  If your device supports multiple
index 78a6c569d204bc0073e33fe093d34a8137e5eaf4..e865279cec5855818d83eb281fcce06ee0510040 100644 (file)
@@ -141,6 +141,14 @@ won't change the current mask settings.  It is more intended as an
 internal API for use by the platform than an external API for use by
 driver writers.
 
+int
+dma_set_mask_and_coherent(struct device *dev, u64 mask)
+
+Checks to see if the mask is possible and updates the device
+streaming and coherent DMA mask parameters if it is.
+
+Returns: 0 if successful and a negative error if not.
+
 int
 dma_set_mask(struct device *dev, u64 mask)
 
index 264e9841563aa6ebb162b545fb3442b85f00c38b..d9995f1f51b3eb9e678a557a471e4d387db49ca8 100644 (file)
@@ -18,17 +18,17 @@ this byte for application use, with the following caveats:
            parameters containing user virtual addresses *must* have
            their top byte cleared before trapping to the kernel.
 
-       (2) Tags are not guaranteed to be preserved when delivering
-           signals. This means that signal handlers in applications
-           making use of tags cannot rely on the tag information for
-           user virtual addresses being maintained for fields inside
-           siginfo_t. One exception to this rule is for signals raised
-           in response to debug exceptions, where the tag information
+       (2) Non-zero tags are not preserved when delivering signals.
+           This means that signal handlers in applications making use
+           of tags cannot rely on the tag information for user virtual
+           addresses being maintained for fields inside siginfo_t.
+           One exception to this rule is for signals raised in response
+           to watchpoint debug exceptions, where the tag information
            will be preserved.
 
        (3) Special care should be taken when using tagged pointers,
            since it is likely that C compilers will not hazard two
-           addresses differing only in the upper bits.
+           virtual addresses differing only in the upper byte.
 
 The architecture prevents the use of a tagged PC, so the upper byte will
 be set to a sign-extension of bit 55 on exception return.
index d18ecd827c408d0fb42a8d8a7fc669ce88c95fc2..929d9904f74b7eb94bac71e81308b0bf335c3108 100644 (file)
@@ -6,6 +6,8 @@ capability.txt
        - Generic Block Device Capability (/sys/block/<device>/capability)
 cfq-iosched.txt
        - CFQ IO scheduler tunables
+cmdline-partition.txt
+       - how to specify block device partitions on kernel command line
 data-integrity.txt
        - Block data integrity
 deadline-iosched.txt
index 2bbf4cc40c3f7f92a02df9bd42b1bdabc8a93791..525b9f6d7fb49e4c9bbd5f7ea76833dcde640e59 100644 (file)
@@ -1,9 +1,9 @@
-Embedded device command line partition
+Embedded device command line partition parsing
 =====================================================================
 
-Read block device partition table from command line.
-The partition used for fixed block device (eMMC) embedded device.
-It is no MBR, save storage space. Bootloader can be easily accessed
+Support for reading the block device partition table from the command line.
+It is typically used for fixed block (eMMC) embedded devices.
+It has no MBR, so saves storage space. Bootloader can be easily accessed
 by absolute address of data on the block device.
 Users can easily change the partition.
 
index 6d1c0988cfc7c7a0466d9f0cc18cc7feacdb0d2b..c67b975c89063f51fa20ae563f601c7c6113fe08 100644 (file)
@@ -1,11 +1,11 @@
-* Samsung Exynos specific extensions to the Synopsis Designware Mobile
+* Samsung Exynos specific extensions to the Synopsys Designware Mobile
   Storage Host Controller
 
-The Synopsis designware mobile storage host controller is used to interface
+The Synopsys designware mobile storage host controller is used to interface
 a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
-differences between the core Synopsis dw mshc controller properties described
-by synopsis-dw-mshc.txt and the properties used by the Samsung Exynos specific
-extensions to the Synopsis Designware Mobile Storage Host Controller.
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Samsung Exynos specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
 
 Required Properties:
 
index 8a3d91d47b6af2e3e99d6182e25f21007b129f94..c559f3f36309e57f1eccda86e926771047960cbb 100644 (file)
@@ -1,11 +1,11 @@
-* Rockchip specific extensions to the Synopsis Designware Mobile
+* Rockchip specific extensions to the Synopsys Designware Mobile
   Storage Host Controller
 
-The Synopsis designware mobile storage host controller is used to interface
+The Synopsys designware mobile storage host controller is used to interface
 a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
-differences between the core Synopsis dw mshc controller properties described
-by synopsis-dw-mshc.txt and the properties used by the Rockchip specific
-extensions to the Synopsis Designware Mobile Storage Host Controller.
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Rockchip specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
 
 Required Properties:
 
similarity index 93%
rename from Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt
rename to Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
index cdcebea9c6f55f55e87f7647d2d8670c04e470b4..066a78b034ca8589e4de4d31183075768496f81a 100644 (file)
@@ -1,14 +1,14 @@
-* Synopsis Designware Mobile Storage Host Controller
+* Synopsys Designware Mobile Storage Host Controller
 
-The Synopsis designware mobile storage host controller is used to interface
+The Synopsys designware mobile storage host controller is used to interface
 a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
 differences between the core mmc properties described by mmc.txt and the
-properties used by the Synopsis Designware Mobile Storage Host Controller.
+properties used by the Synopsys Designware Mobile Storage Host Controller.
 
 Required Properties:
 
 * compatible: should be
-       - snps,dw-mshc: for controllers compliant with synopsis dw-mshc.
+       - snps,dw-mshc: for controllers compliant with synopsys dw-mshc.
 * #address-cells: should be 1.
 * #size-cells: should be 0.
 
index df204e18e030181a23dceebb0bff9de64a84d0a3..6a2a1160a70defdbac92be8850152f1c4448cbde 100644 (file)
@@ -9,12 +9,15 @@ compulsory and any optional properties, common to all SD/MMC drivers, as
 described in mmc.txt, can be used. Additionally the following tmio_mmc-specific
 optional bindings can be used.
 
+Required properties:
+- compatible:  "renesas,sdhi-shmobile" - a generic sh-mobile SDHI unit
+               "renesas,sdhi-sh7372" - SDHI IP on SH7372 SoC
+               "renesas,sdhi-sh73a0" - SDHI IP on SH73A0 SoC
+               "renesas,sdhi-r8a73a4" - SDHI IP on R8A73A4 SoC
+               "renesas,sdhi-r8a7740" - SDHI IP on R8A7740 SoC
+               "renesas,sdhi-r8a7778" - SDHI IP on R8A7778 SoC
+               "renesas,sdhi-r8a7779" - SDHI IP on R8A7779 SoC
+               "renesas,sdhi-r8a7790" - SDHI IP on R8A7790 SoC
+
 Optional properties:
 - toshiba,mmc-wrprotect-disable: write-protect detection is unavailable
-
-When used with Renesas SDHI hardware, the following compatibility strings
-configure various model-specific properties:
-
-"renesas,sh7372-sdhi": (default) compatible with SH7372
-"renesas,r8a7740-sdhi":        compatible with R8A7740: certain MMC/SD commands have to
-                       wait for the interface to become idle.
index 2c6be0377f55d0963970972c4d2b494e73f4507f..d2ea4605d0789dc8d11ff3e1fd8686a30431a43b 100644 (file)
@@ -86,6 +86,7 @@ General Properties:
 
 Clock Properties:
 
+  - fsl,cksel        Timer reference clock source.
   - fsl,tclk-period  Timer reference clock period in nanoseconds.
   - fsl,tmr-prsc     Prescaler, divides the output clock.
   - fsl,tmr-add      Frequency compensation value.
@@ -97,7 +98,7 @@ Clock Properties:
   clock. You must choose these carefully for the clock to work right.
   Here is how to figure good values:
 
-  TimerOsc     = system clock               MHz
+  TimerOsc     = selected reference clock   MHz
   tclk_period  = desired clock period       nanoseconds
   NominalFreq  = 1000 / tclk_period         MHz
   FreqDivRatio = TimerOsc / NominalFreq     (must be greater that 1.0)
@@ -114,6 +115,20 @@ Clock Properties:
   Pulse Per Second (PPS) signal, since this will be offered to the PPS
   subsystem to synchronize the Linux clock.
 
+  Reference clock source is determined by the value, which is holded
+  in CKSEL bits in TMR_CTRL register. "fsl,cksel" property keeps the
+  value, which will be directly written in those bits, that is why,
+  according to reference manual, the next clock sources can be used:
+
+  <0> - external high precision timer reference clock (TSEC_TMR_CLK
+        input is used for this purpose);
+  <1> - eTSEC system clock;
+  <2> - eTSEC1 transmit clock;
+  <3> - RTC clock input.
+
+  When this attribute is not used, eTSEC system clock will serve as
+  IEEE 1588 timer reference clock.
+
 Example:
 
        ptp_clock@24E00 {
@@ -121,6 +136,7 @@ Example:
                reg = <0x24E00 0xB0>;
                interrupts = <12 0x8 13 0x8>;
                interrupt-parent = < &ipic >;
+               fsl,cksel       = <1>;
                fsl,tclk-period = <10>;
                fsl,tmr-prsc    = <100>;
                fsl,tmr-add     = <0x999999A4>;
index eabcb4b5db6e6711b244ea9a35e7b4ff711c12ef..e216af356847c05ac4ab9f2e9a6ae887b1939f2a 100644 (file)
@@ -1,4 +1,4 @@
-* Synopsis Designware PCIe interface
+* Synopsys Designware PCIe interface
 
 Required properties:
 - compatible: should contain "snps,dw-pcie" to identify the
index f93a88250a448a99293d0a6d776af50b1a98453b..deb48b5fd88327d8249b19aa8de16aab6855c191 100644 (file)
@@ -359,11 +359,9 @@ struct inode_operations {
        ssize_t (*listxattr) (struct dentry *, char *, size_t);
        int (*removexattr) (struct dentry *, const char *);
        void (*update_time)(struct inode *, struct timespec *, int);
-       int (*atomic_open)(struct inode *, struct dentry *,
+       int (*atomic_open)(struct inode *, struct dentry *, struct file *,
+                       unsigned open_flag, umode_t create_mode, int *opened);
        int (*tmpfile) (struct inode *, struct dentry *, umode_t);
-} ____cacheline_aligned;
-                               struct file *, unsigned open_flag,
-                               umode_t create_mode, int *opened);
 };
 
 Again, all methods are called without any locks being held, unless
@@ -470,9 +468,11 @@ otherwise noted.
        method the filesystem can look up, possibly create and open the file in
        one atomic operation.  If it cannot perform this (e.g. the file type
        turned out to be wrong) it may signal this by returning 1 instead of
-       usual 0 or -ve .  This method is only called if the last
-       component is negative or needs lookup.  Cached positive dentries are
-       still handled by f_op->open().
+       usual 0 or -ve .  This method is only called if the last component is
+       negative or needs lookup.  Cached positive dentries are still handled by
+       f_op->open().  If the file was created, the FILE_CREATED flag should be
+       set in "opened".  In case of O_EXCL the method must only succeed if the
+       file didn't exist and hence FILE_CREATED shall always be set on success.
 
   tmpfile: called in the end of O_TMPFILE open().  Optional, equivalent to
        atomically creating, opening and unlinking a file in given directory.
index 1a036cd972fb0c205109ed66b968c3d771f66418..fcbb736d55feb439c1152be71355d5ab79f8edd2 100644 (file)
@@ -480,6 +480,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        Format: <io>,<irq>,<mode>
                        See header of drivers/net/hamradio/baycom_ser_hdx.c.
 
+       blkdevparts=    Manual partition parsing of block device(s) for
+                       embedded devices based on command line input.
+                       See Documentation/block/cmdline-partition.txt
+
        boot_delay=     Milliseconds to delay each printk during boot.
                        Values larger than 10 seconds (10000) are changed to
                        no delay (0).
@@ -1357,7 +1361,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        pages. In the event, a node is too small to have both
                        kernelcore and Movable pages, kernelcore pages will
                        take priority and other nodes will have a larger number
-                       of kernelcore pages.  The Movable zone is used for the
+                       of Movable pages.  The Movable zone is used for the
                        allocation of pages that may be reclaimed or moved
                        by the page migration subsystem.  This means that
                        HugeTLB pages may not be allocated from this zone.
@@ -3485,6 +3489,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                                the unplug protocol
                        never -- do not unplug even if version check succeeds
 
+       xen_nopvspin    [X86,XEN]
+                       Disables the ticketlock slowpath using Xen PV
+                       optimizations.
+
        xirc2ps_cs=     [NET,PCMCIA]
                        Format:
                        <irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
index 87bbcfee2e067348c58aead44d54110112dd4a40..9b28e714831ae35fd0664debe4a1091825701024 100644 (file)
@@ -1362,6 +1362,12 @@ To add ARP targets:
 To remove an ARP target:
 # echo -192.168.0.100 > /sys/class/net/bond0/bonding/arp_ip_target
 
+To configure the interval between learning packet transmits:
+# echo 12 > /sys/class/net/bond0/bonding/lp_interval
+       NOTE: the lp_inteval is the number of seconds between instances where
+the bonding driver sends learning packets to each slaves peer switch.  The
+default interval is 1 second.
+
 Example Configuration
 ---------------------
        We begin with the same example that is shown in section 3.3,
index d529e02d928d4750c4acb6f3d6f7de4cf512d12f..f14f4930422224a64ea5e6be2575509e17229e12 100644 (file)
@@ -66,9 +66,7 @@ rq->cfs.load value, which is the sum of the weights of the tasks queued on the
 runqueue.
 
 CFS maintains a time-ordered rbtree, where all runnable tasks are sorted by the
-p->se.vruntime key (there is a subtraction using rq->cfs.min_vruntime to
-account for possible wraparounds).  CFS picks the "leftmost" task from this
-tree and sticks to it.
+p->se.vruntime key. CFS picks the "leftmost" task from this tree and sticks to it.
 As the system progresses forwards, the executed tasks are put into the tree
 more and more to the right --- slowly but surely giving a chance for every task
 to become the "leftmost task" and thus get on the CPU within a deterministic
index a46ddb85e83a0dcdf0f2a54fd9b745eadb31cb6f..f911e3656209f6c1bdc49a156f322b64dfd3a824 100644 (file)
@@ -296,6 +296,12 @@ Cirrus Logic CS4206/4207
   imac27       IMac 27 Inch
   auto         BIOS setup (default)
 
+Cirrus Logic CS4208
+===================
+  mba6         MacBook Air 6,1 and 6,2
+  gpio0                Enable GPIO 0 amp
+  auto         BIOS setup (default)
+
 VIA VT17xx/VT18xx/VT20xx
 ========================
   auto         BIOS setup (default)
index e61c2e83fc2b3b1f7570cff0cc6dc12d87aa8059..8a0cbf3cf2c8c01c5be662eef372eff4060daffc 100644 (file)
@@ -824,15 +824,21 @@ S:        Maintained
 F:     arch/arm/mach-gemini/
 
 ARM/CSR SIRFPRIMA2 MACHINE SUPPORT
-M:     Barry Song <baohua.song@csr.com>
+M:     Barry Song <baohua@kernel.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/baohua/linux.git
 S:     Maintained
 F:     arch/arm/mach-prima2/
+F:     drivers/clk/clk-prima2.c
+F:     drivers/clocksource/timer-prima2.c
+F:     drivers/clocksource/timer-marco.c
 F:     drivers/dma/sirf-dma.c
 F:     drivers/i2c/busses/i2c-sirf.c
+F:     drivers/input/misc/sirfsoc-onkey.c
+F:     drivers/irqchip/irq-sirfsoc.c
 F:     drivers/mmc/host/sdhci-sirf.c
 F:     drivers/pinctrl/sirf/
+F:     drivers/rtc/rtc-sirfsoc.c
 F:     drivers/spi/spi-sirf.c
 
 ARM/EBSA110 MACHINE SUPPORT
@@ -1812,7 +1818,8 @@ S:        Supported
 F:     drivers/net/ethernet/broadcom/bnx2x/
 
 BROADCOM BCM281XX/BCM11XXX ARM ARCHITECTURE
-M:     Christian Daudt <csd@broadcom.com>
+M:     Christian Daudt <bcm@fixthebug.org>
+L:     bcm-kernel-feedback-list@broadcom.com
 T:     git git://git.github.com/broadcom/bcm11351
 S:     Maintained
 F:     arch/arm/mach-bcm/
@@ -2639,6 +2646,18 @@ F:       include/linux/device-mapper.h
 F:     include/linux/dm-*.h
 F:     include/uapi/linux/dm-*.h
 
+DIGI NEO AND CLASSIC PCI PRODUCTS
+M:     Lidza Louina <lidza.louina@gmail.com>
+L:     driverdev-devel@linuxdriverproject.org
+S:     Maintained
+F:     drivers/staging/dgnc/
+
+DIGI EPCA PCI PRODUCTS
+M:     Lidza Louina <lidza.louina@gmail.com>
+L:     driverdev-devel@linuxdriverproject.org
+S:     Maintained
+F:     drivers/staging/dgap/
+
 DIOLAN U2C-12 I2C DRIVER
 M:     Guenter Roeck <linux@roeck-us.net>
 L:     linux-i2c@vger.kernel.org
@@ -4457,6 +4476,13 @@ L:       linux-serial@vger.kernel.org
 S:     Maintained
 F:     drivers/tty/serial/ioc3_serial.c
 
+IOMMU DRIVERS
+M:     Joerg Roedel <joro@8bytes.org>
+L:     iommu@lists.linux-foundation.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
+S:     Maintained
+F:     drivers/iommu/
+
 IP MASQUERADING
 M:     Juanjo Ciarlante <jjciarla@raiz.uncu.edu.ar>
 S:     Maintained
@@ -6595,7 +6621,7 @@ S:        Obsolete
 F:     drivers/net/wireless/prism54/
 
 PROMISE SATA TX2/TX4 CONTROLLER LIBATA DRIVER
-M:     Mikael Pettersson <mikpe@it.uu.se>
+M:     Mikael Pettersson <mikpelinux@gmail.com>
 L:     linux-ide@vger.kernel.org
 S:     Maintained
 F:     drivers/ata/sata_promise.*
@@ -7258,9 +7284,9 @@ F:        include/linux/sched.h
 F:     include/uapi/linux/sched.h
 
 SCORE ARCHITECTURE
-M:     Chen Liqin <liqin.chen@sunplusct.com>
+M:     Chen Liqin <liqin.linux@gmail.com>
 M:     Lennox Wu <lennox.wu@gmail.com>
-W:     http://www.sunplusct.com
+W:     http://www.sunplus.com
 S:     Supported
 F:     arch/score/
 
@@ -8724,9 +8750,8 @@ F:        Documentation/hid/hiddev.txt
 F:     drivers/hid/usbhid/
 
 USB/IP DRIVERS
-M:     Matt Mooney <mfm@muteddisk.com>
 L:     linux-usb@vger.kernel.org
-S:     Maintained
+S:     Orphan
 F:     drivers/staging/usbip/
 
 USB ISP116X DRIVER
@@ -9366,6 +9391,7 @@ F:        arch/arm64/include/asm/xen/
 
 XEN NETWORK BACKEND DRIVER
 M:     Ian Campbell <ian.campbell@citrix.com>
+M:     Wei Liu <wei.liu2@citrix.com>
 L:     xen-devel@lists.xenproject.org (moderated for non-subscribers)
 L:     netdev@vger.kernel.org
 S:     Supported
index de004ceb6b5e32d65e4b21c77855806bf709bbfc..9de9aba21bf9cf9d2a7c467e816417c02b217ecc 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 12
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc4
 NAME = One Giant Leap for Frogkind
 
 # *DOCUMENTATION*
index 1feb169274fe613cc5f0360c797668bf84497c4b..af2cc6eabcc781c4e8f7ee2067de75844ed5874d 100644 (file)
@@ -286,9 +286,6 @@ config HAVE_PERF_USER_STACK_DUMP
 config HAVE_ARCH_JUMP_LABEL
        bool
 
-config HAVE_ARCH_MUTEX_CPU_RELAX
-       bool
-
 config HAVE_RCU_TABLE_FREE
        bool
 
index f158197ac5b04432ac6beb37c9175629361c0901..b6a8c2dfbe6e42cd51def893784f0780bc67264e 100644 (file)
@@ -45,7 +45,14 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock)
 
 static inline void arch_spin_unlock(arch_spinlock_t *lock)
 {
-       lock->slock = __ARCH_SPIN_LOCK_UNLOCKED__;
+       unsigned int tmp = __ARCH_SPIN_LOCK_UNLOCKED__;
+
+       __asm__ __volatile__(
+       "       ex  %0, [%1]            \n"
+       : "+r" (tmp)
+       : "r"(&(lock->slock))
+       : "memory");
+
        smp_mb();
 }
 
index 32420824375b351083da3e8686cc0013f0914871..30c9baffa96f1f3a5cab5d6ec6fe83b9f4e86318 100644 (file)
@@ -43,7 +43,7 @@
  * Because it essentially checks if buffer end is within limit and @len is
  * non-ngeative, which implies that buffer start will be within limit too.
  *
- * The reason for rewriting being, for majorit yof cases, @len is generally
+ * The reason for rewriting being, for majoritof cases, @len is generally
  * compile time constant, causing first sub-expression to be compile time
  * subsumed.
  *
@@ -53,7 +53,7 @@
  *
  */
 #define __user_ok(addr, sz)    (((sz) <= TASK_SIZE) && \
-                                (((addr)+(sz)) <= get_fs()))
+                                ((addr) <= (get_fs() - (sz))))
 #define __access_ok(addr, sz)  (unlikely(__kernel_ok) || \
                                 likely(__user_ok((addr), (sz))))
 
index ee6ef2f60a280c171e42c072401e9b7c1f79ae0c..7e95e1a86510fee2f2e1511f8bc7b63f8fb48122 100644 (file)
@@ -101,7 +101,6 @@ SYSCALL_DEFINE0(rt_sigreturn)
 {
        struct rt_sigframe __user *sf;
        unsigned int magic;
-       int err;
        struct pt_regs *regs = current_pt_regs();
 
        /* Always make any pending restarted system calls return -EINTR */
@@ -119,15 +118,16 @@ SYSCALL_DEFINE0(rt_sigreturn)
        if (!access_ok(VERIFY_READ, sf, sizeof(*sf)))
                goto badframe;
 
-       err = restore_usr_regs(regs, sf);
-       err |= __get_user(magic, &sf->sigret_magic);
-       if (err)
+       if (__get_user(magic, &sf->sigret_magic))
                goto badframe;
 
        if (unlikely(is_do_ss_needed(magic)))
                if (restore_altstack(&sf->uc.uc_stack))
                        goto badframe;
 
+       if (restore_usr_regs(regs, sf))
+               goto badframe;
+
        /* Don't restart from sigreturn */
        syscall_wont_restart(regs);
 
@@ -190,6 +190,15 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info,
        if (!sf)
                return 1;
 
+       /*
+        * w/o SA_SIGINFO, struct ucontext is partially populated (only
+        * uc_mcontext/uc_sigmask) for kernel's normal user state preservation
+        * during signal handler execution. This works for SA_SIGINFO as well
+        * although the semantics are now overloaded (the same reg state can be
+        * inspected by userland: but are they allowed to fiddle with it ?
+        */
+       err |= stash_usr_regs(sf, regs, set);
+
        /*
         * SA_SIGINFO requires 3 args to signal handler:
         *  #1: sig-no (common to any handler)
@@ -213,14 +222,6 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info,
                magic = MAGIC_SIGALTSTK;
        }
 
-       /*
-        * w/o SA_SIGINFO, struct ucontext is partially populated (only
-        * uc_mcontext/uc_sigmask) for kernel's normal user state preservation
-        * during signal handler execution. This works for SA_SIGINFO as well
-        * although the semantics are now overloaded (the same reg state can be
-        * inspected by userland: but are they allowed to fiddle with it ?
-        */
-       err |= stash_usr_regs(sf, regs, set);
        err |= __put_user(magic, &sf->sigret_magic);
        if (err)
                return err;
index 0e51e69cf30d772b646ef8a1d2c5605bf63b929a..3fde7de3ea670351ac69e0f441f35f776ebbb7d8 100644 (file)
@@ -227,12 +227,9 @@ void __attribute__((weak)) arc_local_timer_setup(unsigned int cpu)
 {
        struct clock_event_device *clk = &per_cpu(arc_clockevent_device, cpu);
 
-       clockevents_calc_mult_shift(clk, arc_get_core_freq(), 5);
-
-       clk->max_delta_ns = clockevent_delta2ns(ARC_TIMER_MAX, clk);
        clk->cpumask = cpumask_of(cpu);
-
-       clockevents_register_device(clk);
+       clockevents_config_and_register(clk, arc_get_core_freq(),
+                                       0, ARC_TIMER_MAX);
 
        /*
         * setup the per-cpu timer IRQ handler - for all cpus
index 28d1700607474eb01be14e0600832bf7ee4cf999..7ff5b5c183bb026716295c13f7b123de1d67a96f 100644 (file)
@@ -245,6 +245,12 @@ int misaligned_fixup(unsigned long address, struct pt_regs *regs,
                regs->status32 &= ~STATUS_DE_MASK;
        } else {
                regs->ret += state.instr_len;
+
+               /* handle zero-overhead-loop */
+               if ((regs->ret == regs->lp_end) && (regs->lp_count)) {
+                       regs->ret = regs->lp_start;
+                       regs->lp_count--;
+               }
        }
 
        return 0;
index 1ad6fb6c094db415ec76a72a28356e75bdfd7d17..c06647d9f10314684f7a56f0ddeb0257d0211eaa 100644 (file)
@@ -5,6 +5,7 @@ config ARM
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
        select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
        select ARCH_HAVE_CUSTOM_GPIO_H
+       select ARCH_USE_CMPXCHG_LOCKREF
        select ARCH_WANT_IPC_PARSE_VERSION
        select BUILDTIME_EXTABLE_SORT if MMU
        select CLONE_BACKWARDS
@@ -51,6 +52,8 @@ config ARM
        select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND
        select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
        select HAVE_PERF_EVENTS
+       select HAVE_PERF_REGS
+       select HAVE_PERF_USER_STACK_DUMP
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_SYSCALL_TRACEPOINTS
        select HAVE_UID16
@@ -692,7 +695,6 @@ config ARCH_SA1100
        select GENERIC_CLOCKEVENTS
        select HAVE_IDE
        select ISA
-       select NEED_MACH_GPIO_H
        select NEED_MACH_MEMORY_H
        select SPARSE_IRQ
        help
@@ -1549,6 +1551,32 @@ config MCPM
          for (multi-)cluster based systems, such as big.LITTLE based
          systems.
 
+config BIG_LITTLE
+       bool "big.LITTLE support (Experimental)"
+       depends on CPU_V7 && SMP
+       select MCPM
+       help
+         This option enables support selections for the big.LITTLE
+         system architecture.
+
+config BL_SWITCHER
+       bool "big.LITTLE switcher support"
+       depends on BIG_LITTLE && MCPM && HOTPLUG_CPU
+       select CPU_PM
+       select ARM_CPU_SUSPEND
+       help
+         The big.LITTLE "switcher" provides the core functionality to
+         transparently handle transition between a cluster of A15's
+         and a cluster of A7's in a big.LITTLE system.
+
+config BL_SWITCHER_DUMMY_IF
+       tristate "Simple big.LITTLE switcher user interface"
+       depends on BL_SWITCHER && DEBUG_KERNEL
+       help
+         This is a simple and dummy char dev interface to control
+         the big.LITTLE switcher core code.  It is meant for
+         debugging purposes only.
+
 choice
        prompt "Memory split"
        default VMSPLIT_3G
index 9762c84b419845f05ee6a7d1f9f95084dde310b5..2b3206824353f612d3c72e81eae0b1a157f9d1c7 100644 (file)
@@ -834,6 +834,20 @@ choice
                  options; the platform specific options are deprecated
                  and will be soon removed.
 
+       config DEBUG_LL_UART_EFM32
+               bool "Kernel low-level debugging via efm32 UART"
+               depends on ARCH_EFM32
+               help
+                 Say Y here if you want the debug print routines to direct
+                 their output to an UART or USART port on efm32 based
+                 machines. Use the following addresses for DEBUG_UART_PHYS:
+
+                   0x4000c000 | USART0
+                   0x4000c400 | USART1
+                   0x4000c800 | USART2
+                   0x4000e000 | UART0
+                   0x4000e400 | UART1
+
        config DEBUG_LL_UART_PL01X
                bool "Kernel low-level debugging via ARM Ltd PL01x Primecell UART"
                help
@@ -885,6 +899,7 @@ config DEBUG_LL_INCLUDE
        default "debug/8250.S" if DEBUG_LL_UART_8250 || DEBUG_UART_8250
        default "debug/pl01x.S" if DEBUG_LL_UART_PL01X || DEBUG_UART_PL01X
        default "debug/exynos.S" if DEBUG_EXYNOS_UART
+       default "debug/efm32.S" if DEBUG_LL_UART_EFM32
        default "debug/icedcc.S" if DEBUG_ICEDCC
        default "debug/imx.S" if DEBUG_IMX1_UART || \
                                 DEBUG_IMX25_UART || \
@@ -951,6 +966,7 @@ config DEBUG_UART_PHYS
        default 0x20064000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2
        default 0x20068000 if DEBUG_RK29_UART2 || DEBUG_RK3X_UART3
        default 0x20201000 if DEBUG_BCM2835
+       default 0x4000e400 if DEBUG_LL_UART_EFM32
        default 0x40090000 if ARCH_LPC32XX
        default 0x40100000 if DEBUG_PXA_UART1
        default 0x42000000 if ARCH_GEMINI
@@ -981,6 +997,7 @@ config DEBUG_UART_PHYS
        default 0xfff36000 if DEBUG_HIGHBANK_UART
        default 0xfffff700 if ARCH_IOP33X
        depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
+               DEBUG_LL_UART_EFM32 || \
                DEBUG_UART_8250 || DEBUG_UART_PL01X
 
 config DEBUG_UART_VIRT
index cc0f1fb61753963d0d6f0a81d63f5d969c100d42..802720e3e8fd5c72004c14cce0bc572a0355356a 100644 (file)
@@ -41,6 +41,8 @@ dtb-$(CONFIG_ARCH_AT91)       += sama5d33ek.dtb
 dtb-$(CONFIG_ARCH_AT91)        += sama5d34ek.dtb
 dtb-$(CONFIG_ARCH_AT91)        += sama5d35ek.dtb
 
+dtb-$(CONFIG_ARCH_ATLAS6) += atlas6-evb.dtb
+
 dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb
 dtb-$(CONFIG_ARCH_BCM) += bcm11351-brt.dtb \
        bcm28155-ap.dtb
@@ -183,6 +185,7 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
        am335x-evm.dtb \
        am335x-evmsk.dtb \
        am335x-bone.dtb \
+       am335x-boneblack.dtb \
        am3517-evm.dtb \
        am3517_mt_ventoux.dtb \
        am43x-epos-evm.dtb
diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
new file mode 100644 (file)
index 0000000..2f66ded
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/ {
+       model = "TI AM335x BeagleBone";
+       compatible = "ti,am335x-bone", "ti,am33xx";
+
+       cpus {
+               cpu@0 {
+                       cpu0-supply = <&dcdc2_reg>;
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x10000000>; /* 256 MB */
+       };
+
+       am33xx_pinmux: pinmux@44e10800 {
+               pinctrl-names = "default";
+               pinctrl-0 = <&clkout2_pin>;
+
+               user_leds_s0: user_leds_s0 {
+                       pinctrl-single,pins = <
+                               0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)  /* gpmc_a5.gpio1_21 */
+                               0x58 (PIN_OUTPUT_PULLUP | MUX_MODE7)    /* gpmc_a6.gpio1_22 */
+                               0x5c (PIN_OUTPUT_PULLDOWN | MUX_MODE7)  /* gpmc_a7.gpio1_23 */
+                               0x60 (PIN_OUTPUT_PULLUP | MUX_MODE7)    /* gpmc_a8.gpio1_24 */
+                       >;
+               };
+
+               i2c0_pins: pinmux_i2c0_pins {
+                       pinctrl-single,pins = <
+                               0x188 (PIN_INPUT_PULLUP | MUX_MODE0)    /* i2c0_sda.i2c0_sda */
+                               0x18c (PIN_INPUT_PULLUP | MUX_MODE0)    /* i2c0_scl.i2c0_scl */
+                       >;
+               };
+
+               uart0_pins: pinmux_uart0_pins {
+                       pinctrl-single,pins = <
+                               0x170 (PIN_INPUT_PULLUP | MUX_MODE0)    /* uart0_rxd.uart0_rxd */
+                               0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
+                       >;
+               };
+
+               clkout2_pin: pinmux_clkout2_pin {
+                       pinctrl-single,pins = <
+                               0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */
+                       >;
+               };
+
+               cpsw_default: cpsw_default {
+                       pinctrl-single,pins = <
+                               /* Slave 1 */
+                               0x110 (PIN_INPUT_PULLUP | MUX_MODE0)    /* mii1_rxerr.mii1_rxerr */
+                               0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txen.mii1_txen */
+                               0x118 (PIN_INPUT_PULLUP | MUX_MODE0)    /* mii1_rxdv.mii1_rxdv */
+                               0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd3.mii1_txd3 */
+                               0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd2.mii1_txd2 */
+                               0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd1.mii1_txd1 */
+                               0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd0.mii1_txd0 */
+                               0x12c (PIN_INPUT_PULLUP | MUX_MODE0)    /* mii1_txclk.mii1_txclk */
+                               0x130 (PIN_INPUT_PULLUP | MUX_MODE0)    /* mii1_rxclk.mii1_rxclk */
+                               0x134 (PIN_INPUT_PULLUP | MUX_MODE0)    /* mii1_rxd3.mii1_rxd3 */
+                               0x138 (PIN_INPUT_PULLUP | MUX_MODE0)    /* mii1_rxd2.mii1_rxd2 */
+                               0x13c (PIN_INPUT_PULLUP | MUX_MODE0)    /* mii1_rxd1.mii1_rxd1 */
+                               0x140 (PIN_INPUT_PULLUP | MUX_MODE0)    /* mii1_rxd0.mii1_rxd0 */
+                       >;
+               };
+
+               cpsw_sleep: cpsw_sleep {
+                       pinctrl-single,pins = <
+                               /* Slave 1 reset value */
+                               0x110 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                               0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                               0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                               0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                               0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                               0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                               0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                               0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                               0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                               0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                               0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                               0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                               0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       >;
+               };
+
+               davinci_mdio_default: davinci_mdio_default {
+                       pinctrl-single,pins = <
+                               /* MDIO */
+                               0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)    /* mdio_data.mdio_data */
+                               0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)                   /* mdio_clk.mdio_clk */
+                       >;
+               };
+
+               davinci_mdio_sleep: davinci_mdio_sleep {
+                       pinctrl-single,pins = <
+                               /* MDIO reset value */
+                               0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                               0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       >;
+               };
+       };
+
+       ocp {
+               uart0: serial@44e09000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&uart0_pins>;
+
+                       status = "okay";
+               };
+
+               musb: usb@47400000 {
+                       status = "okay";
+
+                       control@44e10000 {
+                               status = "okay";
+                       };
+
+                       usb-phy@47401300 {
+                               status = "okay";
+                       };
+
+                       usb-phy@47401b00 {
+                               status = "okay";
+                       };
+
+                       usb@47401000 {
+                               status = "okay";
+                       };
+
+                       usb@47401800 {
+                               status = "okay";
+                               dr_mode = "host";
+                       };
+
+                       dma-controller@07402000  {
+                               status = "okay";
+                       };
+               };
+
+               i2c0: i2c@44e0b000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&i2c0_pins>;
+
+                       status = "okay";
+                       clock-frequency = <400000>;
+
+                       tps: tps@24 {
+                               reg = <0x24>;
+                       };
+
+               };
+       };
+
+       leds {
+               pinctrl-names = "default";
+               pinctrl-0 = <&user_leds_s0>;
+
+               compatible = "gpio-leds";
+
+               led@2 {
+                       label = "beaglebone:green:heartbeat";
+                       gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "heartbeat";
+                       default-state = "off";
+               };
+
+               led@3 {
+                       label = "beaglebone:green:mmc0";
+                       gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "mmc0";
+                       default-state = "off";
+               };
+
+               led@4 {
+                       label = "beaglebone:green:usr2";
+                       gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+
+               led@5 {
+                       label = "beaglebone:green:usr3";
+                       gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+       };
+};
+
+/include/ "tps65217.dtsi"
+
+&tps {
+       regulators {
+               dcdc1_reg: regulator@0 {
+                       regulator-always-on;
+               };
+
+               dcdc2_reg: regulator@1 {
+                       /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+                       regulator-name = "vdd_mpu";
+                       regulator-min-microvolt = <925000>;
+                       regulator-max-microvolt = <1325000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+               };
+
+               dcdc3_reg: regulator@2 {
+                       /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+                       regulator-name = "vdd_core";
+                       regulator-min-microvolt = <925000>;
+                       regulator-max-microvolt = <1150000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+               };
+
+               ldo1_reg: regulator@3 {
+                       regulator-always-on;
+               };
+
+               ldo2_reg: regulator@4 {
+                       regulator-always-on;
+               };
+
+               ldo3_reg: regulator@5 {
+                       regulator-always-on;
+               };
+
+               ldo4_reg: regulator@6 {
+                       regulator-always-on;
+               };
+       };
+};
+
+&cpsw_emac0 {
+       phy_id = <&davinci_mdio>, <0>;
+       phy-mode = "mii";
+};
+
+&cpsw_emac1 {
+       phy_id = <&davinci_mdio>, <1>;
+       phy-mode = "mii";
+};
+
+&mac {
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&cpsw_default>;
+       pinctrl-1 = <&cpsw_sleep>;
+
+};
+
+&davinci_mdio {
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&davinci_mdio_default>;
+       pinctrl-1 = <&davinci_mdio_sleep>;
+};
index d318987d44a1931931f553eaad143c54efc53280..7993c489982c86ab2cf03a85b152f9b7db99ad3f 100644 (file)
@@ -8,258 +8,4 @@
 /dts-v1/;
 
 #include "am33xx.dtsi"
-
-/ {
-       model = "TI AM335x BeagleBone";
-       compatible = "ti,am335x-bone", "ti,am33xx";
-
-       cpus {
-               cpu@0 {
-                       cpu0-supply = <&dcdc2_reg>;
-               };
-       };
-
-       memory {
-               device_type = "memory";
-               reg = <0x80000000 0x10000000>; /* 256 MB */
-       };
-
-       am33xx_pinmux: pinmux@44e10800 {
-               pinctrl-names = "default";
-               pinctrl-0 = <&clkout2_pin>;
-
-               user_leds_s0: user_leds_s0 {
-                       pinctrl-single,pins = <
-                               0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)  /* gpmc_a5.gpio1_21 */
-                               0x58 (PIN_OUTPUT_PULLUP | MUX_MODE7)    /* gpmc_a6.gpio1_22 */
-                               0x5c (PIN_OUTPUT_PULLDOWN | MUX_MODE7)  /* gpmc_a7.gpio1_23 */
-                               0x60 (PIN_OUTPUT_PULLUP | MUX_MODE7)    /* gpmc_a8.gpio1_24 */
-                       >;
-               };
-
-               i2c0_pins: pinmux_i2c0_pins {
-                       pinctrl-single,pins = <
-                               0x188 (PIN_INPUT_PULLUP | MUX_MODE0)    /* i2c0_sda.i2c0_sda */
-                               0x18c (PIN_INPUT_PULLUP | MUX_MODE0)    /* i2c0_scl.i2c0_scl */
-                       >;
-               };
-
-               uart0_pins: pinmux_uart0_pins {
-                       pinctrl-single,pins = <
-                               0x170 (PIN_INPUT_PULLUP | MUX_MODE0)    /* uart0_rxd.uart0_rxd */
-                               0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
-                       >;
-               };
-
-               clkout2_pin: pinmux_clkout2_pin {
-                       pinctrl-single,pins = <
-                               0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */
-                       >;
-               };
-
-               cpsw_default: cpsw_default {
-                       pinctrl-single,pins = <
-                               /* Slave 1 */
-                               0x110 (PIN_INPUT_PULLUP | MUX_MODE0)    /* mii1_rxerr.mii1_rxerr */
-                               0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txen.mii1_txen */
-                               0x118 (PIN_INPUT_PULLUP | MUX_MODE0)    /* mii1_rxdv.mii1_rxdv */
-                               0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd3.mii1_txd3 */
-                               0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd2.mii1_txd2 */
-                               0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd1.mii1_txd1 */
-                               0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd0.mii1_txd0 */
-                               0x12c (PIN_INPUT_PULLUP | MUX_MODE0)    /* mii1_txclk.mii1_txclk */
-                               0x130 (PIN_INPUT_PULLUP | MUX_MODE0)    /* mii1_rxclk.mii1_rxclk */
-                               0x134 (PIN_INPUT_PULLUP | MUX_MODE0)    /* mii1_rxd3.mii1_rxd3 */
-                               0x138 (PIN_INPUT_PULLUP | MUX_MODE0)    /* mii1_rxd2.mii1_rxd2 */
-                               0x13c (PIN_INPUT_PULLUP | MUX_MODE0)    /* mii1_rxd1.mii1_rxd1 */
-                               0x140 (PIN_INPUT_PULLUP | MUX_MODE0)    /* mii1_rxd0.mii1_rxd0 */
-                       >;
-               };
-
-               cpsw_sleep: cpsw_sleep {
-                       pinctrl-single,pins = <
-                               /* Slave 1 reset value */
-                               0x110 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-                               0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-                               0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-                               0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-                               0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-                               0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-                               0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-                               0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-                               0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-                               0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-                               0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-                               0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-                               0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       >;
-               };
-
-               davinci_mdio_default: davinci_mdio_default {
-                       pinctrl-single,pins = <
-                               /* MDIO */
-                               0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)    /* mdio_data.mdio_data */
-                               0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)                   /* mdio_clk.mdio_clk */
-                       >;
-               };
-
-               davinci_mdio_sleep: davinci_mdio_sleep {
-                       pinctrl-single,pins = <
-                               /* MDIO reset value */
-                               0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-                               0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-                       >;
-               };
-       };
-
-       ocp {
-               uart0: serial@44e09000 {
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&uart0_pins>;
-
-                       status = "okay";
-               };
-
-               musb: usb@47400000 {
-                       status = "okay";
-
-                       control@44e10000 {
-                               status = "okay";
-                       };
-
-                       usb-phy@47401300 {
-                               status = "okay";
-                       };
-
-                       usb-phy@47401b00 {
-                               status = "okay";
-                       };
-
-                       usb@47401000 {
-                               status = "okay";
-                       };
-
-                       usb@47401800 {
-                               status = "okay";
-                               dr_mode = "host";
-                       };
-
-                       dma-controller@07402000  {
-                               status = "okay";
-                       };
-               };
-
-               i2c0: i2c@44e0b000 {
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&i2c0_pins>;
-
-                       status = "okay";
-                       clock-frequency = <400000>;
-
-                       tps: tps@24 {
-                               reg = <0x24>;
-                       };
-
-               };
-       };
-
-       leds {
-               pinctrl-names = "default";
-               pinctrl-0 = <&user_leds_s0>;
-
-               compatible = "gpio-leds";
-
-               led@2 {
-                       label = "beaglebone:green:heartbeat";
-                       gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "heartbeat";
-                       default-state = "off";
-               };
-
-               led@3 {
-                       label = "beaglebone:green:mmc0";
-                       gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "mmc0";
-                       default-state = "off";
-               };
-
-               led@4 {
-                       label = "beaglebone:green:usr2";
-                       gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
-                       default-state = "off";
-               };
-
-               led@5 {
-                       label = "beaglebone:green:usr3";
-                       gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
-                       default-state = "off";
-               };
-       };
-};
-
-/include/ "tps65217.dtsi"
-
-&tps {
-       regulators {
-               dcdc1_reg: regulator@0 {
-                       regulator-always-on;
-               };
-
-               dcdc2_reg: regulator@1 {
-                       /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
-                       regulator-name = "vdd_mpu";
-                       regulator-min-microvolt = <925000>;
-                       regulator-max-microvolt = <1325000>;
-                       regulator-boot-on;
-                       regulator-always-on;
-               };
-
-               dcdc3_reg: regulator@2 {
-                       /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
-                       regulator-name = "vdd_core";
-                       regulator-min-microvolt = <925000>;
-                       regulator-max-microvolt = <1150000>;
-                       regulator-boot-on;
-                       regulator-always-on;
-               };
-
-               ldo1_reg: regulator@3 {
-                       regulator-always-on;
-               };
-
-               ldo2_reg: regulator@4 {
-                       regulator-always-on;
-               };
-
-               ldo3_reg: regulator@5 {
-                       regulator-always-on;
-               };
-
-               ldo4_reg: regulator@6 {
-                       regulator-always-on;
-               };
-       };
-};
-
-&cpsw_emac0 {
-       phy_id = <&davinci_mdio>, <0>;
-       phy-mode = "mii";
-};
-
-&cpsw_emac1 {
-       phy_id = <&davinci_mdio>, <1>;
-       phy-mode = "mii";
-};
-
-&mac {
-       pinctrl-names = "default", "sleep";
-       pinctrl-0 = <&cpsw_default>;
-       pinctrl-1 = <&cpsw_sleep>;
-
-};
-
-&davinci_mdio {
-       pinctrl-names = "default", "sleep";
-       pinctrl-0 = <&davinci_mdio_default>;
-       pinctrl-1 = <&davinci_mdio_sleep>;
-};
+#include "am335x-bone-common.dtsi"
diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
new file mode 100644 (file)
index 0000000..197cadf
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+
+&ldo3_reg {
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <1800000>;
+       regulator-always-on;
+};
index 05e4485a822521ec1ca234c7991c674f817f4667..8ac2ac1f69cc0d6f50101c815fada7c9183ce9d8 100644 (file)
        };
 
        soc {
+               ranges = <MBUS_ID(0xf0, 0x01) 0 0xd0000000 0x100000
+                         MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000>;
+
+               pcie-controller {
+                       status = "okay";
+
+                       /* Connected to Marvell SATA controller */
+                       pcie@1,0 {
+                               /* Port 0, Lane 0 */
+                               status = "okay";
+                       };
+
+                       /* Connected to FL1009 USB 3.0 controller */
+                       pcie@2,0 {
+                               /* Port 1, Lane 0 */
+                               status = "okay";
+                       };
+               };
+
                internal-regs {
                        serial@12000 {
                                clock-frequency = <200000000>;
                                        marvell,pins = "mpp56";
                                        marvell,function = "gpio";
                                };
+
+                               poweroff: poweroff {
+                                       marvell,pins = "mpp8";
+                                       marvell,function = "gpio";
+                               };
                        };
 
                        mdio {
                                        pwm_polarity = <0>;
                                };
                        };
-
-                       pcie-controller {
-                               status = "okay";
-
-                               /* Connected to Marvell SATA controller */
-                               pcie@1,0 {
-                                       /* Port 0, Lane 0 */
-                                       status = "okay";
-                               };
-
-                               /* Connected to FL1009 USB 3.0 controller */
-                               pcie@2,0 {
-                                       /* Port 1, Lane 0 */
-                                       status = "okay";
-                               };
-                       };
                };
        };
 
                button@1 {
                        label = "Power Button";
                        linux,code = <116>;     /* KEY_POWER */
-                       gpios = <&gpio1 30 1>;
+                       gpios = <&gpio1 30 0>;
                };
 
                button@2 {
                };
        };
 
+       gpio_poweroff {
+               compatible = "gpio-poweroff";
+               pinctrl-0 = <&poweroff>;
+               pinctrl-names = "default";
+               gpios = <&gpio0 8 1>;
+       };
+
 };
index def125c0eeaa1596892f5cda162667d99853827c..3058522f5aad2929092f7f7bcc2dd78a9c62c22a 100644 (file)
@@ -70,6 +70,8 @@
 
                        timer@20300 {
                                compatible = "marvell,armada-xp-timer";
+                               clocks = <&coreclk 2>, <&refclk>;
+                               clock-names = "nbclk", "fixed";
                        };
 
                        coreclk: mvebu-sar@18230 {
                        };
                };
        };
+
+       clocks {
+               /* 25 MHz reference crystal */
+               refclk: oscillator {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <25000000>;
+               };
+       };
 };
index cf78ac0b04b12f77a3bc707e0228ce19a9e09785..e74dc15efa9d2f77fa339a16b975f42566ca726e 100644 (file)
                                                         AT91_PIOA 8 AT91_PERIPH_A AT91_PINCTRL_NONE>;  /* PA8 periph A */
                                        };
 
-                                       pinctrl_uart2_rts: uart2_rts-0 {
+                                       pinctrl_usart2_rts: usart2_rts-0 {
                                                atmel,pins =
                                                        <AT91_PIOB 0 AT91_PERIPH_B AT91_PINCTRL_NONE>;  /* PB0 periph B */
                                        };
 
-                                       pinctrl_uart2_cts: uart2_cts-0 {
+                                       pinctrl_usart2_cts: usart2_cts-0 {
                                                atmel,pins =
                                                        <AT91_PIOB 1 AT91_PERIPH_B AT91_PINCTRL_NONE>;  /* PB1 periph B */
                                        };
                                interrupts = <12 IRQ_TYPE_LEVEL_HIGH 0>;
                                dmas = <&dma0 1 AT91_DMA_CFG_PER_ID(0)>;
                                dma-names = "rxtx";
+                               pinctrl-names = "default";
                                #address-cells = <1>;
                                #size-cells = <0>;
                                status = "disabled";
                                interrupts = <26 IRQ_TYPE_LEVEL_HIGH 0>;
                                dmas = <&dma1 1 AT91_DMA_CFG_PER_ID(0)>;
                                dma-names = "rxtx";
+                               pinctrl-names = "default";
                                #address-cells = <1>;
                                #size-cells = <0>;
                                status = "disabled";
index 8678e0c1111981be494cfe6fecf05eb61a393169..6db4f81d4795d2855b83aac5a72cc3c7b8cb6727 100644 (file)
                                interrupts = <17>;
                                fifosize = <128>;
                                clocks = <&clks 13>;
+                               sirf,uart-dma-rx-channel = <21>;
+                               sirf,uart-dma-tx-channel = <2>;
                        };
 
                        uart1: uart@b0060000 {
                                interrupts = <19>;
                                fifosize = <128>;
                                clocks = <&clks 15>;
+                               sirf,uart-dma-rx-channel = <6>;
+                               sirf,uart-dma-tx-channel = <7>;
                        };
 
                        usp0: usp@b0080000 {
                                compatible = "sirf,prima2-usp";
                                reg = <0xb0080000 0x10000>;
                                interrupts = <20>;
+                               fifosize = <128>;
                                clocks = <&clks 28>;
+                               sirf,usp-dma-rx-channel = <17>;
+                               sirf,usp-dma-tx-channel = <18>;
                        };
 
                        usp1: usp@b0090000 {
                                compatible = "sirf,prima2-usp";
                                reg = <0xb0090000 0x10000>;
                                interrupts = <21>;
+                               fifosize = <128>;
                                clocks = <&clks 29>;
+                               sirf,usp-dma-rx-channel = <14>;
+                               sirf,usp-dma-tx-channel = <15>;
                        };
 
                        dmac0: dma-controller@b00b0000 {
                                compatible = "sirf,prima2-vip";
                                reg = <0xb00C0000 0x10000>;
                                clocks = <&clks 31>;
+                               interrupts = <14>;
+                               sirf,vip-dma-rx-channel = <16>;
                        };
 
                        spi0: spi@b00d0000 {
index c037c223619a7a9ced403c88f1146fb20c112378..b7a1c6d950b984b44efd65c100c05024c80c1b4a 100644 (file)
                                compatible = "fsl,imx27-cspi";
                                reg = <0x1000e000 0x1000>;
                                interrupts = <16>;
-                               clocks = <&clks 53>, <&clks 53>;
+                               clocks = <&clks 53>, <&clks 60>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
                                compatible = "fsl,imx27-cspi";
                                reg = <0x1000f000 0x1000>;
                                interrupts = <15>;
-                               clocks = <&clks 52>, <&clks 52>;
+                               clocks = <&clks 52>, <&clks 60>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
                                compatible = "fsl,imx27-cspi";
                                reg = <0x10017000 0x1000>;
                                interrupts = <6>;
-                               clocks = <&clks 51>, <&clks 51>;
+                               clocks = <&clks 51>, <&clks 60>;
                                clock-names = "ipg", "per";
                                status = "disabled";
                        };
index a85abb424c3482d02dd325ae388bcf63686acc56..54cee6517902d647507f3ed40302135fcba1b849 100644 (file)
                                compatible = "fsl,imx51-pata", "fsl,imx27-pata";
                                reg = <0x83fe0000 0x4000>;
                                interrupts = <70>;
-                               clocks = <&clks 161>;
+                               clocks = <&clks 172>;
                                status = "disabled";
                        };
 
index c0e38a45e4bb487493ed8400328eb27d8a8965b2..9bbe82bdee4112ca0b15de05118b70472b04287c 100644 (file)
 #define MX6QDL_PAD_EIM_D29__ECSPI4_SS0              0x0c8 0x3dc 0x824 0x2 0x1
 #define MX6QDL_PAD_EIM_D29__UART2_RTS_B             0x0c8 0x3dc 0x924 0x4 0x1
 #define MX6QDL_PAD_EIM_D29__UART2_CTS_B             0x0c8 0x3dc 0x000 0x4 0x0
-#define MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B         0x0c4 0x3dc 0x000 0x4 0x0
-#define MX6QDL_PAD_EIM_D29__UART2_DTE_CTS_B         0x0c4 0x3dc 0x924 0x4 0x1
+#define MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B         0x0c8 0x3dc 0x000 0x4 0x0
+#define MX6QDL_PAD_EIM_D29__UART2_DTE_CTS_B         0x0c8 0x3dc 0x924 0x4 0x1
 #define MX6QDL_PAD_EIM_D29__GPIO3_IO29              0x0c8 0x3dc 0x000 0x5 0x0
 #define MX6QDL_PAD_EIM_D29__IPU2_CSI1_VSYNC         0x0c8 0x3dc 0x8e4 0x6 0x0
 #define MX6QDL_PAD_EIM_D29__IPU1_DI0_PIN14          0x0c8 0x3dc 0x000 0x7 0x0
index cf7aeaf89e9c1a6b8795113e0726c48b58f16803..1335b2e1bed4c66efe95ee2f679129d3856ccb43 100644 (file)
@@ -13,6 +13,7 @@
                cpu@0 {
                        device_type = "cpu";
                        compatible = "marvell,feroceon";
+                       reg = <0>;
                        clocks = <&core_clk 1>, <&core_clk 3>, <&gate_clk 11>;
                        clock-names = "cpu_clk", "ddrclk", "powersave";
                };
                xor@60900 {
                        compatible = "marvell,orion-xor";
                        reg = <0x60900 0x100
-                              0xd0B00 0x100>;
+                              0x60B00 0x100>;
                        status = "okay";
                        clocks = <&gate_clk 16>;
 
index afdb16417d4e894bc2df369cd7c229a5b7161043..0c514dc8460c2423299848748278a452638e535c 100644 (file)
@@ -11,7 +11,7 @@
 
 / {
        model = "TI OMAP3 BeagleBoard xM";
-       compatible = "ti,omap3-beagle-xmti,omap3-beagle", "ti,omap3";
+       compatible = "ti,omap3-beagle-xm", "ti,omap3-beagle", "ti,omap3";
 
        cpus {
                cpu@0 {
index bc48b114eae6404cf0e12ff08113f0bfd6002cf5..2326d11462a57dcb9e43991b359f63ce14da1520 100644 (file)
                >;
        };
 
+       mcbsp2_pins: pinmux_mcbsp2_pins {
+               pinctrl-single,pins = <
+                       0x10c (PIN_INPUT | MUX_MODE0)           /* mcbsp2_fsx.mcbsp2_fsx */
+                       0x10e (PIN_INPUT | MUX_MODE0)           /* mcbsp2_clkx.mcbsp2_clkx */
+                       0x110 (PIN_INPUT | MUX_MODE0)           /* mcbsp2_dr.mcbsp2.dr */
+                       0x112 (PIN_OUTPUT | MUX_MODE0)          /* mcbsp2_dx.mcbsp2_dx */
+               >;
+       };
+
        mmc1_pins: pinmux_mmc1_pins {
                pinctrl-single,pins = <
                        0x114 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc1_clk.sdmmc1_clk */
        clock-frequency = <400000>;
 };
 
+&mcbsp2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mcbsp2_pins>;
+};
+
 &mmc1 {
       pinctrl-names = "default";
       pinctrl-0 = <&mmc1_pins>;
index faa95b5b242ee437aeea84c8d4dde915a67c2031..814ab67c8c299b0b818f669c917d51ebcb8a94c0 100644 (file)
         */
                clock-frequency = <19200000>;
        };
+
+       /* regulator for wl12xx on sdio5 */
+       wl12xx_vmmc: wl12xx_vmmc {
+               pinctrl-names = "default";
+               pinctrl-0 = <&wl12xx_gpio>;
+               compatible = "regulator-fixed";
+               regulator-name = "vwl1271";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               gpio = <&gpio2 11 0>;
+               startup-delay-us = <70000>;
+               enable-active-high;
+       };
 };
 
 &omap4_pmx_wkup {
                        0x1c (PIN_OUTPUT | MUX_MODE3)   /* gpio_wk8 */
                >;
        };
+
+       /*
+        * wl12xx GPIO outputs for WLAN_EN, BT_EN, FM_EN, BT_WAKEUP
+        * REVISIT: Are the pull-ups needed for GPIO 48 and 49?
+        */
+       wl12xx_gpio: pinmux_wl12xx_gpio {
+               pinctrl-single,pins = <
+                       0x26 (PIN_OUTPUT | MUX_MODE3)           /* gpmc_a19.gpio_43 */
+                       0x2c (PIN_OUTPUT | MUX_MODE3)           /* gpmc_a22.gpio_46 */
+                       0x30 (PIN_OUTPUT_PULLUP | MUX_MODE3)    /* gpmc_a24.gpio_48 */
+                       0x32 (PIN_OUTPUT_PULLUP | MUX_MODE3)    /* gpmc_a25.gpio_49 */
+               >;
+       };
+
+       /* wl12xx GPIO inputs and SDIO pins */
+       wl12xx_pins: pinmux_wl12xx_pins {
+               pinctrl-single,pins = <
+                       0x38 (PIN_INPUT | MUX_MODE3)            /* gpmc_ncs2.gpio_52 */
+                       0x3a (PIN_INPUT | MUX_MODE3)            /* gpmc_ncs3.gpio_53 */
+                       0x108 (PIN_OUTPUT | MUX_MODE0)          /* sdmmc5_clk.sdmmc5_clk */
+                       0x10a (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_cmd.sdmmc5_cmd */
+                       0x10c (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat0.sdmmc5_dat0 */
+                       0x10e (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat1.sdmmc5_dat1 */
+                       0x110 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat2.sdmmc5_dat2 */
+                       0x112 (PIN_INPUT_PULLUP | MUX_MODE0)    /* sdmmc5_dat3.sdmmc5_dat3 */
+               >;
+       };
 };
 
 &i2c1 {
 };
 
 &mmc5 {
-       ti,non-removable;
+       pinctrl-names = "default";
+       pinctrl-0 = <&wl12xx_pins>;
+       vmmc-supply = <&wl12xx_vmmc>;
+       non-removable;
        bus-width = <4>;
+       cap-power-off-card;
 };
 
 &emif1 {
index 7951b4ea500af37ac2a4f6b8f59e97cbf263d595..4f78380ecdb890c5b72cae0ac8937365540d80bd 100644 (file)
                        "DMic", "Digital Mic",
                        "Digital Mic", "Digital Mic1 Bias";
        };
+
+       /* regulator for wl12xx on sdio5 */
+       wl12xx_vmmc: wl12xx_vmmc {
+               pinctrl-names = "default";
+               pinctrl-0 = <&wl12xx_gpio>;
+               compatible = "regulator-fixed";
+               regulator-name = "vwl1271";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               gpio = <&gpio2 22 0>;
+               startup-delay-us = <70000>;
+               enable-active-high;
+       };
 };
 
 &omap4_pmx_wkup {
                        0xf0 (PIN_INPUT_PULLUP | MUX_MODE0)     /* i2c4_sda */
                >;
        };
+
+       /* wl12xx GPIO output for WLAN_EN */
+       wl12xx_gpio: pinmux_wl12xx_gpio {
+               pinctrl-single,pins = <
+                       0x3c (PIN_OUTPUT | MUX_MODE3)           /* gpmc_nwp.gpio_54 */
+               >;
+       };
+
+       /* wl12xx GPIO inputs and SDIO pins */
+       wl12xx_pins: pinmux_wl12xx_pins {
+               pinctrl-single,pins = <
+                       0x3a (PIN_INPUT | MUX_MODE3)            /* gpmc_ncs3.gpio_53 */
+                       0x108 (PIN_OUTPUT | MUX_MODE3)          /* sdmmc5_clk.sdmmc5_clk */
+                       0x10a (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_cmd.sdmmc5_cmd */
+                       0x10c (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_dat0.sdmmc5_dat0 */
+                       0x10e (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_dat1.sdmmc5_dat1 */
+                       0x110 (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_dat2.sdmmc5_dat2 */
+                       0x112 (PIN_INPUT_PULLUP | MUX_MODE3)    /* sdmmc5_dat3.sdmmc5_dat3 */
+               >;
+       };
 };
 
 &i2c1 {
 };
 
 &mmc5 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&wl12xx_pins>;
+       vmmc-supply = <&wl12xx_vmmc>;
+       non-removable;
        bus-width = <4>;
-       ti,non-removable;
+       cap-power-off-card;
 };
 
 &emif1 {
index 07be2cd7b3188f6c943b1928e812dfa676973bfb..7cdea1bfea091917455e46cc18af7d6d80a2c0f0 100644 (file)
                omap_dwc3@4a020000 {
                        compatible = "ti,dwc3";
                        ti,hwmods = "usb_otg_ss";
-                       reg = <0x4a020000 0x1000>;
+                       reg = <0x4a020000 0x10000>;
                        interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges;
                        dwc3@4a030000 {
                                compatible = "snps,dwc3";
-                               reg = <0x4a030000 0x1000>;
+                               reg = <0x4a030000 0x10000>;
                                interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
                                usb-phy = <&usb2_phy>, <&usb3_phy>;
                                tx-fifo-resize;
                        };
                };
 
-               ocp2scp {
+               ocp2scp@4a080000 {
                        compatible = "ti,omap-ocp2scp";
                        #address-cells = <1>;
                        #size-cells = <1>;
+                       reg = <0x4a080000 0x20>;
                        ranges;
                        ti,hwmods = "ocp2scp1";
                        usb2_phy: usb2phy@4a084000 {
index bbeb623fc2c6f82dc9f92b1c77a90811946f9736..27ed9f5144bcb927d777cf4468c1ddaa5c11c837 100644 (file)
                        compatible = "simple-bus";
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       ranges = <0xb0000000 0xb0000000 0x180000>;
+                       ranges = <0xb0000000 0xb0000000 0x180000>,
+                              <0x56000000 0x56000000 0x1b00000>;
 
                        timer@b0020000 {
                                compatible = "sirf,prima2-tick";
                        uart0: uart@b0050000 {
                                cell-index = <0>;
                                compatible = "sirf,prima2-uart";
-                               reg = <0xb0050000 0x10000>;
+                               reg = <0xb0050000 0x1000>;
                                interrupts = <17>;
+                               fifosize = <128>;
                                clocks = <&clks 13>;
+                               sirf,uart-dma-rx-channel = <21>;
+                               sirf,uart-dma-tx-channel = <2>;
                        };
 
                        uart1: uart@b0060000 {
                                cell-index = <1>;
                                compatible = "sirf,prima2-uart";
-                               reg = <0xb0060000 0x10000>;
+                               reg = <0xb0060000 0x1000>;
                                interrupts = <18>;
+                               fifosize = <32>;
                                clocks = <&clks 14>;
                        };
 
                        uart2: uart@b0070000 {
                                cell-index = <2>;
                                compatible = "sirf,prima2-uart";
-                               reg = <0xb0070000 0x10000>;
+                               reg = <0xb0070000 0x1000>;
                                interrupts = <19>;
+                               fifosize = <128>;
                                clocks = <&clks 15>;
+                               sirf,uart-dma-rx-channel = <6>;
+                               sirf,uart-dma-tx-channel = <7>;
                        };
 
                        usp0: usp@b0080000 {
                                compatible = "sirf,prima2-usp";
                                reg = <0xb0080000 0x10000>;
                                interrupts = <20>;
+                               fifosize = <128>;
                                clocks = <&clks 28>;
+                               sirf,usp-dma-rx-channel = <17>;
+                               sirf,usp-dma-tx-channel = <18>;
                        };
 
                        usp1: usp@b0090000 {
                                compatible = "sirf,prima2-usp";
                                reg = <0xb0090000 0x10000>;
                                interrupts = <21>;
+                               fifosize = <128>;
                                clocks = <&clks 29>;
+                               sirf,usp-dma-rx-channel = <14>;
+                               sirf,usp-dma-tx-channel = <15>;
                        };
 
                        usp2: usp@b00a0000 {
                                compatible = "sirf,prima2-usp";
                                reg = <0xb00a0000 0x10000>;
                                interrupts = <22>;
+                               fifosize = <128>;
                                clocks = <&clks 30>;
+                               sirf,usp-dma-rx-channel = <10>;
+                               sirf,usp-dma-tx-channel = <11>;
                        };
 
                        dmac0: dma-controller@b00b0000 {
                                compatible = "sirf,prima2-vip";
                                reg = <0xb00C0000 0x10000>;
                                clocks = <&clks 31>;
+                               interrupts = <14>;
+                               sirf,vip-dma-rx-channel = <16>;
                        };
 
                        spi0: spi@b00d0000 {
index 6c26caa880f2917344ada23a6a8e8e106412a0f9..658fcc537576b309ae06ecb74eaf65b3e3f2856c 100644 (file)
        };
 
        sdhi0: sdhi@ee100000 {
-               compatible = "renesas,r8a73a4-sdhi";
+               compatible = "renesas,sdhi-r8a73a4";
                reg = <0 0xee100000 0 0x100>;
                interrupt-parent = <&gic>;
                interrupts = <0 165 4>;
        };
 
        sdhi1: sdhi@ee120000 {
-               compatible = "renesas,r8a73a4-sdhi";
+               compatible = "renesas,sdhi-r8a73a4";
                reg = <0 0xee120000 0 0x100>;
                interrupt-parent = <&gic>;
                interrupts = <0 166 4>;
        };
 
        sdhi2: sdhi@ee140000 {
-               compatible = "renesas,r8a73a4-sdhi";
+               compatible = "renesas,sdhi-r8a73a4";
                reg = <0 0xee140000 0 0x100>;
                interrupt-parent = <&gic>;
                interrupts = <0 167 4>;
index 45ac404ab6d8b79b246f6f5724f3609b48bf58cb..3577aba8258336bab80d44c3065c6e94f6ffe8a7 100644 (file)
@@ -96,6 +96,5 @@
        pfc: pfc@fffc0000 {
                compatible = "renesas,pfc-r8a7778";
                reg = <0xfffc000 0x118>;
-               #gpio-range-cells = <3>;
        };
 };
index 23a62447359c1a690f354bada3f3dbcabcbf6286..ebbe507fcbfa118280da96482dfaa109854f18c8 100644 (file)
        pfc: pfc@fffc0000 {
                compatible = "renesas,pfc-r8a7779";
                reg = <0xfffc0000 0x23c>;
-               #gpio-range-cells = <3>;
        };
 
        thermal@ffc48000 {
index 3b879e7c697c336748d5f35adf6744c6d7e14458..413b4c29e782d7ded622563b8a458e28d382db19 100644 (file)
        pfc: pfc@e6060000 {
                compatible = "renesas,pfc-r8a7790";
                reg = <0 0xe6060000 0 0x250>;
-               #gpio-range-cells = <3>;
        };
 
        sdhi0: sdhi@ee100000 {
-               compatible = "renesas,r8a7790-sdhi";
+               compatible = "renesas,sdhi-r8a7790";
                reg = <0 0xee100000 0 0x100>;
                interrupt-parent = <&gic>;
                interrupts = <0 165 4>;
        };
 
        sdhi1: sdhi@ee120000 {
-               compatible = "renesas,r8a7790-sdhi";
+               compatible = "renesas,sdhi-r8a7790";
                reg = <0 0xee120000 0 0x100>;
                interrupt-parent = <&gic>;
                interrupts = <0 166 4>;
        };
 
        sdhi2: sdhi@ee140000 {
-               compatible = "renesas,r8a7790-sdhi";
+               compatible = "renesas,sdhi-r8a7790";
                reg = <0 0xee140000 0 0x100>;
                interrupt-parent = <&gic>;
                interrupts = <0 167 4>;
        };
 
        sdhi3: sdhi@ee160000 {
-               compatible = "renesas,r8a7790-sdhi";
+               compatible = "renesas,sdhi-r8a7790";
                reg = <0 0xee160000 0 0x100>;
                interrupt-parent = <&gic>;
                interrupts = <0 168 4>;
index ba59a5875a10689d14fd96d9102e21814baf2a54..3955c7606a6f45a33036bec612ad918806315dee 100644 (file)
        };
 
        sdhi0: sdhi@ee100000 {
-               compatible = "renesas,r8a7740-sdhi";
+               compatible = "renesas,sdhi-r8a7740";
                reg = <0xee100000 0x100>;
                interrupt-parent = <&gic>;
                interrupts = <0 83 4
 
        /* SDHI1 and SDHI2 have no CD pins, no need for CD IRQ */
        sdhi1: sdhi@ee120000 {
-               compatible = "renesas,r8a7740-sdhi";
+               compatible = "renesas,sdhi-r8a7740";
                reg = <0xee120000 0x100>;
                interrupt-parent = <&gic>;
                interrupts = <0 88 4
        };
 
        sdhi2: sdhi@ee140000 {
-               compatible = "renesas,r8a7740-sdhi";
+               compatible = "renesas,sdhi-r8a7740";
                reg = <0xee140000 0x100>;
                interrupt-parent = <&gic>;
                interrupts = <0 104 4
index 8c60f473e97625cb8c0bb068375da7368d1ff6fe..5c8584c4944d780f90bcedb40b8224fb60fa364f 100644 (file)
@@ -17,3 +17,5 @@ obj-$(CONFIG_MCPM)            += mcpm_head.o mcpm_entry.o mcpm_platsmp.o vlock.o
 AFLAGS_mcpm_head.o             := -march=armv7-a
 AFLAGS_vlock.o                 := -march=armv7-a
 obj-$(CONFIG_TI_PRIV_EDMA)     += edma.o
+obj-$(CONFIG_BL_SWITCHER)      += bL_switcher.o
+obj-$(CONFIG_BL_SWITCHER_DUMMY_IF) += bL_switcher_dummy_if.o
diff --git a/arch/arm/common/bL_switcher.c b/arch/arm/common/bL_switcher.c
new file mode 100644 (file)
index 0000000..63bbc4f
--- /dev/null
@@ -0,0 +1,822 @@
+/*
+ * arch/arm/common/bL_switcher.c -- big.LITTLE cluster switcher core driver
+ *
+ * Created by: Nicolas Pitre, March 2012
+ * Copyright:  (C) 2012-2013  Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/atomic.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/cpu_pm.h>
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
+#include <linux/time.h>
+#include <linux/clockchips.h>
+#include <linux/hrtimer.h>
+#include <linux/tick.h>
+#include <linux/notifier.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+#include <linux/irqchip/arm-gic.h>
+#include <linux/moduleparam.h>
+
+#include <asm/smp_plat.h>
+#include <asm/cputype.h>
+#include <asm/suspend.h>
+#include <asm/mcpm.h>
+#include <asm/bL_switcher.h>
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/power_cpu_migrate.h>
+
+
+/*
+ * Use our own MPIDR accessors as the generic ones in asm/cputype.h have
+ * __attribute_const__ and we don't want the compiler to assume any
+ * constness here as the value _does_ change along some code paths.
+ */
+
+static int read_mpidr(void)
+{
+       unsigned int id;
+       asm volatile ("mrc p15, 0, %0, c0, c0, 5" : "=r" (id));
+       return id & MPIDR_HWID_BITMASK;
+}
+
+/*
+ * Get a global nanosecond time stamp for tracing.
+ */
+static s64 get_ns(void)
+{
+       struct timespec ts;
+       getnstimeofday(&ts);
+       return timespec_to_ns(&ts);
+}
+
+/*
+ * bL switcher core code.
+ */
+
+static void bL_do_switch(void *_arg)
+{
+       unsigned ib_mpidr, ib_cpu, ib_cluster;
+       long volatile handshake, **handshake_ptr = _arg;
+
+       pr_debug("%s\n", __func__);
+
+       ib_mpidr = cpu_logical_map(smp_processor_id());
+       ib_cpu = MPIDR_AFFINITY_LEVEL(ib_mpidr, 0);
+       ib_cluster = MPIDR_AFFINITY_LEVEL(ib_mpidr, 1);
+
+       /* Advertise our handshake location */
+       if (handshake_ptr) {
+               handshake = 0;
+               *handshake_ptr = &handshake;
+       } else
+               handshake = -1;
+
+       /*
+        * Our state has been saved at this point.  Let's release our
+        * inbound CPU.
+        */
+       mcpm_set_entry_vector(ib_cpu, ib_cluster, cpu_resume);
+       sev();
+
+       /*
+        * From this point, we must assume that our counterpart CPU might
+        * have taken over in its parallel world already, as if execution
+        * just returned from cpu_suspend().  It is therefore important to
+        * be very careful not to make any change the other guy is not
+        * expecting.  This is why we need stack isolation.
+        *
+        * Fancy under cover tasks could be performed here.  For now
+        * we have none.
+        */
+
+       /*
+        * Let's wait until our inbound is alive.
+        */
+       while (!handshake) {
+               wfe();
+               smp_mb();
+       }
+
+       /* Let's put ourself down. */
+       mcpm_cpu_power_down();
+
+       /* should never get here */
+       BUG();
+}
+
+/*
+ * Stack isolation.  To ensure 'current' remains valid, we just use another
+ * piece of our thread's stack space which should be fairly lightly used.
+ * The selected area starts just above the thread_info structure located
+ * at the very bottom of the stack, aligned to a cache line, and indexed
+ * with the cluster number.
+ */
+#define STACK_SIZE 512
+extern void call_with_stack(void (*fn)(void *), void *arg, void *sp);
+static int bL_switchpoint(unsigned long _arg)
+{
+       unsigned int mpidr = read_mpidr();
+       unsigned int clusterid = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+       void *stack = current_thread_info() + 1;
+       stack = PTR_ALIGN(stack, L1_CACHE_BYTES);
+       stack += clusterid * STACK_SIZE + STACK_SIZE;
+       call_with_stack(bL_do_switch, (void *)_arg, stack);
+       BUG();
+}
+
+/*
+ * Generic switcher interface
+ */
+
+static unsigned int bL_gic_id[MAX_CPUS_PER_CLUSTER][MAX_NR_CLUSTERS];
+static int bL_switcher_cpu_pairing[NR_CPUS];
+
+/*
+ * bL_switch_to - Switch to a specific cluster for the current CPU
+ * @new_cluster_id: the ID of the cluster to switch to.
+ *
+ * This function must be called on the CPU to be switched.
+ * Returns 0 on success, else a negative status code.
+ */
+static int bL_switch_to(unsigned int new_cluster_id)
+{
+       unsigned int mpidr, this_cpu, that_cpu;
+       unsigned int ob_mpidr, ob_cpu, ob_cluster, ib_mpidr, ib_cpu, ib_cluster;
+       struct completion inbound_alive;
+       struct tick_device *tdev;
+       enum clock_event_mode tdev_mode;
+       long volatile *handshake_ptr;
+       int ipi_nr, ret;
+
+       this_cpu = smp_processor_id();
+       ob_mpidr = read_mpidr();
+       ob_cpu = MPIDR_AFFINITY_LEVEL(ob_mpidr, 0);
+       ob_cluster = MPIDR_AFFINITY_LEVEL(ob_mpidr, 1);
+       BUG_ON(cpu_logical_map(this_cpu) != ob_mpidr);
+
+       if (new_cluster_id == ob_cluster)
+               return 0;
+
+       that_cpu = bL_switcher_cpu_pairing[this_cpu];
+       ib_mpidr = cpu_logical_map(that_cpu);
+       ib_cpu = MPIDR_AFFINITY_LEVEL(ib_mpidr, 0);
+       ib_cluster = MPIDR_AFFINITY_LEVEL(ib_mpidr, 1);
+
+       pr_debug("before switch: CPU %d MPIDR %#x -> %#x\n",
+                this_cpu, ob_mpidr, ib_mpidr);
+
+       this_cpu = smp_processor_id();
+
+       /* Close the gate for our entry vectors */
+       mcpm_set_entry_vector(ob_cpu, ob_cluster, NULL);
+       mcpm_set_entry_vector(ib_cpu, ib_cluster, NULL);
+
+       /* Install our "inbound alive" notifier. */
+       init_completion(&inbound_alive);
+       ipi_nr = register_ipi_completion(&inbound_alive, this_cpu);
+       ipi_nr |= ((1 << 16) << bL_gic_id[ob_cpu][ob_cluster]);
+       mcpm_set_early_poke(ib_cpu, ib_cluster, gic_get_sgir_physaddr(), ipi_nr);
+
+       /*
+        * Let's wake up the inbound CPU now in case it requires some delay
+        * to come online, but leave it gated in our entry vector code.
+        */
+       ret = mcpm_cpu_power_up(ib_cpu, ib_cluster);
+       if (ret) {
+               pr_err("%s: mcpm_cpu_power_up() returned %d\n", __func__, ret);
+               return ret;
+       }
+
+       /*
+        * Raise a SGI on the inbound CPU to make sure it doesn't stall
+        * in a possible WFI, such as in bL_power_down().
+        */
+       gic_send_sgi(bL_gic_id[ib_cpu][ib_cluster], 0);
+
+       /*
+        * Wait for the inbound to come up.  This allows for other
+        * tasks to be scheduled in the mean time.
+        */
+       wait_for_completion(&inbound_alive);
+       mcpm_set_early_poke(ib_cpu, ib_cluster, 0, 0);
+
+       /*
+        * From this point we are entering the switch critical zone
+        * and can't take any interrupts anymore.
+        */
+       local_irq_disable();
+       local_fiq_disable();
+       trace_cpu_migrate_begin(get_ns(), ob_mpidr);
+
+       /* redirect GIC's SGIs to our counterpart */
+       gic_migrate_target(bL_gic_id[ib_cpu][ib_cluster]);
+
+       tdev = tick_get_device(this_cpu);
+       if (tdev && !cpumask_equal(tdev->evtdev->cpumask, cpumask_of(this_cpu)))
+               tdev = NULL;
+       if (tdev) {
+               tdev_mode = tdev->evtdev->mode;
+               clockevents_set_mode(tdev->evtdev, CLOCK_EVT_MODE_SHUTDOWN);
+       }
+
+       ret = cpu_pm_enter();
+
+       /* we can not tolerate errors at this point */
+       if (ret)
+               panic("%s: cpu_pm_enter() returned %d\n", __func__, ret);
+
+       /* Swap the physical CPUs in the logical map for this logical CPU. */
+       cpu_logical_map(this_cpu) = ib_mpidr;
+       cpu_logical_map(that_cpu) = ob_mpidr;
+
+       /* Let's do the actual CPU switch. */
+       ret = cpu_suspend((unsigned long)&handshake_ptr, bL_switchpoint);
+       if (ret > 0)
+               panic("%s: cpu_suspend() returned %d\n", __func__, ret);
+
+       /* We are executing on the inbound CPU at this point */
+       mpidr = read_mpidr();
+       pr_debug("after switch: CPU %d MPIDR %#x\n", this_cpu, mpidr);
+       BUG_ON(mpidr != ib_mpidr);
+
+       mcpm_cpu_powered_up();
+
+       ret = cpu_pm_exit();
+
+       if (tdev) {
+               clockevents_set_mode(tdev->evtdev, tdev_mode);
+               clockevents_program_event(tdev->evtdev,
+                                         tdev->evtdev->next_event, 1);
+       }
+
+       trace_cpu_migrate_finish(get_ns(), ib_mpidr);
+       local_fiq_enable();
+       local_irq_enable();
+
+       *handshake_ptr = 1;
+       dsb_sev();
+
+       if (ret)
+               pr_err("%s exiting with error %d\n", __func__, ret);
+       return ret;
+}
+
+struct bL_thread {
+       spinlock_t lock;
+       struct task_struct *task;
+       wait_queue_head_t wq;
+       int wanted_cluster;
+       struct completion started;
+       bL_switch_completion_handler completer;
+       void *completer_cookie;
+};
+
+static struct bL_thread bL_threads[NR_CPUS];
+
+static int bL_switcher_thread(void *arg)
+{
+       struct bL_thread *t = arg;
+       struct sched_param param = { .sched_priority = 1 };
+       int cluster;
+       bL_switch_completion_handler completer;
+       void *completer_cookie;
+
+       sched_setscheduler_nocheck(current, SCHED_FIFO, &param);
+       complete(&t->started);
+
+       do {
+               if (signal_pending(current))
+                       flush_signals(current);
+               wait_event_interruptible(t->wq,
+                               t->wanted_cluster != -1 ||
+                               kthread_should_stop());
+
+               spin_lock(&t->lock);
+               cluster = t->wanted_cluster;
+               completer = t->completer;
+               completer_cookie = t->completer_cookie;
+               t->wanted_cluster = -1;
+               t->completer = NULL;
+               spin_unlock(&t->lock);
+
+               if (cluster != -1) {
+                       bL_switch_to(cluster);
+
+                       if (completer)
+                               completer(completer_cookie);
+               }
+       } while (!kthread_should_stop());
+
+       return 0;
+}
+
+static struct task_struct *bL_switcher_thread_create(int cpu, void *arg)
+{
+       struct task_struct *task;
+
+       task = kthread_create_on_node(bL_switcher_thread, arg,
+                                     cpu_to_node(cpu), "kswitcher_%d", cpu);
+       if (!IS_ERR(task)) {
+               kthread_bind(task, cpu);
+               wake_up_process(task);
+       } else
+               pr_err("%s failed for CPU %d\n", __func__, cpu);
+       return task;
+}
+
+/*
+ * bL_switch_request_cb - Switch to a specific cluster for the given CPU,
+ *      with completion notification via a callback
+ *
+ * @cpu: the CPU to switch
+ * @new_cluster_id: the ID of the cluster to switch to.
+ * @completer: switch completion callback.  if non-NULL,
+ *     @completer(@completer_cookie) will be called on completion of
+ *     the switch, in non-atomic context.
+ * @completer_cookie: opaque context argument for @completer.
+ *
+ * This function causes a cluster switch on the given CPU by waking up
+ * the appropriate switcher thread.  This function may or may not return
+ * before the switch has occurred.
+ *
+ * If a @completer callback function is supplied, it will be called when
+ * the switch is complete.  This can be used to determine asynchronously
+ * when the switch is complete, regardless of when bL_switch_request()
+ * returns.  When @completer is supplied, no new switch request is permitted
+ * for the affected CPU until after the switch is complete, and @completer
+ * has returned.
+ */
+int bL_switch_request_cb(unsigned int cpu, unsigned int new_cluster_id,
+                        bL_switch_completion_handler completer,
+                        void *completer_cookie)
+{
+       struct bL_thread *t;
+
+       if (cpu >= ARRAY_SIZE(bL_threads)) {
+               pr_err("%s: cpu %d out of bounds\n", __func__, cpu);
+               return -EINVAL;
+       }
+
+       t = &bL_threads[cpu];
+
+       if (IS_ERR(t->task))
+               return PTR_ERR(t->task);
+       if (!t->task)
+               return -ESRCH;
+
+       spin_lock(&t->lock);
+       if (t->completer) {
+               spin_unlock(&t->lock);
+               return -EBUSY;
+       }
+       t->completer = completer;
+       t->completer_cookie = completer_cookie;
+       t->wanted_cluster = new_cluster_id;
+       spin_unlock(&t->lock);
+       wake_up(&t->wq);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(bL_switch_request_cb);
+
+/*
+ * Activation and configuration code.
+ */
+
+static DEFINE_MUTEX(bL_switcher_activation_lock);
+static BLOCKING_NOTIFIER_HEAD(bL_activation_notifier);
+static unsigned int bL_switcher_active;
+static unsigned int bL_switcher_cpu_original_cluster[NR_CPUS];
+static cpumask_t bL_switcher_removed_logical_cpus;
+
+int bL_switcher_register_notifier(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_register(&bL_activation_notifier, nb);
+}
+EXPORT_SYMBOL_GPL(bL_switcher_register_notifier);
+
+int bL_switcher_unregister_notifier(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_unregister(&bL_activation_notifier, nb);
+}
+EXPORT_SYMBOL_GPL(bL_switcher_unregister_notifier);
+
+static int bL_activation_notify(unsigned long val)
+{
+       int ret;
+
+       ret = blocking_notifier_call_chain(&bL_activation_notifier, val, NULL);
+       if (ret & NOTIFY_STOP_MASK)
+               pr_err("%s: notifier chain failed with status 0x%x\n",
+                       __func__, ret);
+       return notifier_to_errno(ret);
+}
+
+static void bL_switcher_restore_cpus(void)
+{
+       int i;
+
+       for_each_cpu(i, &bL_switcher_removed_logical_cpus)
+               cpu_up(i);
+}
+
+static int bL_switcher_halve_cpus(void)
+{
+       int i, j, cluster_0, gic_id, ret;
+       unsigned int cpu, cluster, mask;
+       cpumask_t available_cpus;
+
+       /* First pass to validate what we have */
+       mask = 0;
+       for_each_online_cpu(i) {
+               cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(i), 0);
+               cluster = MPIDR_AFFINITY_LEVEL(cpu_logical_map(i), 1);
+               if (cluster >= 2) {
+                       pr_err("%s: only dual cluster systems are supported\n", __func__);
+                       return -EINVAL;
+               }
+               if (WARN_ON(cpu >= MAX_CPUS_PER_CLUSTER))
+                       return -EINVAL;
+               mask |= (1 << cluster);
+       }
+       if (mask != 3) {
+               pr_err("%s: no CPU pairing possible\n", __func__);
+               return -EINVAL;
+       }
+
+       /*
+        * Now let's do the pairing.  We match each CPU with another CPU
+        * from a different cluster.  To get a uniform scheduling behavior
+        * without fiddling with CPU topology and compute capacity data,
+        * we'll use logical CPUs initially belonging to the same cluster.
+        */
+       memset(bL_switcher_cpu_pairing, -1, sizeof(bL_switcher_cpu_pairing));
+       cpumask_copy(&available_cpus, cpu_online_mask);
+       cluster_0 = -1;
+       for_each_cpu(i, &available_cpus) {
+               int match = -1;
+               cluster = MPIDR_AFFINITY_LEVEL(cpu_logical_map(i), 1);
+               if (cluster_0 == -1)
+                       cluster_0 = cluster;
+               if (cluster != cluster_0)
+                       continue;
+               cpumask_clear_cpu(i, &available_cpus);
+               for_each_cpu(j, &available_cpus) {
+                       cluster = MPIDR_AFFINITY_LEVEL(cpu_logical_map(j), 1);
+                       /*
+                        * Let's remember the last match to create "odd"
+                        * pairings on purpose in order for other code not
+                        * to assume any relation between physical and
+                        * logical CPU numbers.
+                        */
+                       if (cluster != cluster_0)
+                               match = j;
+               }
+               if (match != -1) {
+                       bL_switcher_cpu_pairing[i] = match;
+                       cpumask_clear_cpu(match, &available_cpus);
+                       pr_info("CPU%d paired with CPU%d\n", i, match);
+               }
+       }
+
+       /*
+        * Now we disable the unwanted CPUs i.e. everything that has no
+        * pairing information (that includes the pairing counterparts).
+        */
+       cpumask_clear(&bL_switcher_removed_logical_cpus);
+       for_each_online_cpu(i) {
+               cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(i), 0);
+               cluster = MPIDR_AFFINITY_LEVEL(cpu_logical_map(i), 1);
+
+               /* Let's take note of the GIC ID for this CPU */
+               gic_id = gic_get_cpu_id(i);
+               if (gic_id < 0) {
+                       pr_err("%s: bad GIC ID for CPU %d\n", __func__, i);
+                       bL_switcher_restore_cpus();
+                       return -EINVAL;
+               }
+               bL_gic_id[cpu][cluster] = gic_id;
+               pr_info("GIC ID for CPU %u cluster %u is %u\n",
+                       cpu, cluster, gic_id);
+
+               if (bL_switcher_cpu_pairing[i] != -1) {
+                       bL_switcher_cpu_original_cluster[i] = cluster;
+                       continue;
+               }
+
+               ret = cpu_down(i);
+               if (ret) {
+                       bL_switcher_restore_cpus();
+                       return ret;
+               }
+               cpumask_set_cpu(i, &bL_switcher_removed_logical_cpus);
+       }
+
+       return 0;
+}
+
+/* Determine the logical CPU a given physical CPU is grouped on. */
+int bL_switcher_get_logical_index(u32 mpidr)
+{
+       int cpu;
+
+       if (!bL_switcher_active)
+               return -EUNATCH;
+
+       mpidr &= MPIDR_HWID_BITMASK;
+       for_each_online_cpu(cpu) {
+               int pairing = bL_switcher_cpu_pairing[cpu];
+               if (pairing == -1)
+                       continue;
+               if ((mpidr == cpu_logical_map(cpu)) ||
+                   (mpidr == cpu_logical_map(pairing)))
+                       return cpu;
+       }
+       return -EINVAL;
+}
+
+static void bL_switcher_trace_trigger_cpu(void *__always_unused info)
+{
+       trace_cpu_migrate_current(get_ns(), read_mpidr());
+}
+
+int bL_switcher_trace_trigger(void)
+{
+       int ret;
+
+       preempt_disable();
+
+       bL_switcher_trace_trigger_cpu(NULL);
+       ret = smp_call_function(bL_switcher_trace_trigger_cpu, NULL, true);
+
+       preempt_enable();
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(bL_switcher_trace_trigger);
+
+static int bL_switcher_enable(void)
+{
+       int cpu, ret;
+
+       mutex_lock(&bL_switcher_activation_lock);
+       cpu_hotplug_driver_lock();
+       if (bL_switcher_active) {
+               cpu_hotplug_driver_unlock();
+               mutex_unlock(&bL_switcher_activation_lock);
+               return 0;
+       }
+
+       pr_info("big.LITTLE switcher initializing\n");
+
+       ret = bL_activation_notify(BL_NOTIFY_PRE_ENABLE);
+       if (ret)
+               goto error;
+
+       ret = bL_switcher_halve_cpus();
+       if (ret)
+               goto error;
+
+       bL_switcher_trace_trigger();
+
+       for_each_online_cpu(cpu) {
+               struct bL_thread *t = &bL_threads[cpu];
+               spin_lock_init(&t->lock);
+               init_waitqueue_head(&t->wq);
+               init_completion(&t->started);
+               t->wanted_cluster = -1;
+               t->task = bL_switcher_thread_create(cpu, t);
+       }
+
+       bL_switcher_active = 1;
+       bL_activation_notify(BL_NOTIFY_POST_ENABLE);
+       pr_info("big.LITTLE switcher initialized\n");
+       goto out;
+
+error:
+       pr_warn("big.LITTLE switcher initialization failed\n");
+       bL_activation_notify(BL_NOTIFY_POST_DISABLE);
+
+out:
+       cpu_hotplug_driver_unlock();
+       mutex_unlock(&bL_switcher_activation_lock);
+       return ret;
+}
+
+#ifdef CONFIG_SYSFS
+
+static void bL_switcher_disable(void)
+{
+       unsigned int cpu, cluster;
+       struct bL_thread *t;
+       struct task_struct *task;
+
+       mutex_lock(&bL_switcher_activation_lock);
+       cpu_hotplug_driver_lock();
+
+       if (!bL_switcher_active)
+               goto out;
+
+       if (bL_activation_notify(BL_NOTIFY_PRE_DISABLE) != 0) {
+               bL_activation_notify(BL_NOTIFY_POST_ENABLE);
+               goto out;
+       }
+
+       bL_switcher_active = 0;
+
+       /*
+        * To deactivate the switcher, we must shut down the switcher
+        * threads to prevent any other requests from being accepted.
+        * Then, if the final cluster for given logical CPU is not the
+        * same as the original one, we'll recreate a switcher thread
+        * just for the purpose of switching the CPU back without any
+        * possibility for interference from external requests.
+        */
+       for_each_online_cpu(cpu) {
+               t = &bL_threads[cpu];
+               task = t->task;
+               t->task = NULL;
+               if (!task || IS_ERR(task))
+                       continue;
+               kthread_stop(task);
+               /* no more switch may happen on this CPU at this point */
+               cluster = MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 1);
+               if (cluster == bL_switcher_cpu_original_cluster[cpu])
+                       continue;
+               init_completion(&t->started);
+               t->wanted_cluster = bL_switcher_cpu_original_cluster[cpu];
+               task = bL_switcher_thread_create(cpu, t);
+               if (!IS_ERR(task)) {
+                       wait_for_completion(&t->started);
+                       kthread_stop(task);
+                       cluster = MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 1);
+                       if (cluster == bL_switcher_cpu_original_cluster[cpu])
+                               continue;
+               }
+               /* If execution gets here, we're in trouble. */
+               pr_crit("%s: unable to restore original cluster for CPU %d\n",
+                       __func__, cpu);
+               pr_crit("%s: CPU %d can't be restored\n",
+                       __func__, bL_switcher_cpu_pairing[cpu]);
+               cpumask_clear_cpu(bL_switcher_cpu_pairing[cpu],
+                                 &bL_switcher_removed_logical_cpus);
+       }
+
+       bL_switcher_restore_cpus();
+       bL_switcher_trace_trigger();
+
+       bL_activation_notify(BL_NOTIFY_POST_DISABLE);
+
+out:
+       cpu_hotplug_driver_unlock();
+       mutex_unlock(&bL_switcher_activation_lock);
+}
+
+static ssize_t bL_switcher_active_show(struct kobject *kobj,
+               struct kobj_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%u\n", bL_switcher_active);
+}
+
+static ssize_t bL_switcher_active_store(struct kobject *kobj,
+               struct kobj_attribute *attr, const char *buf, size_t count)
+{
+       int ret;
+
+       switch (buf[0]) {
+       case '0':
+               bL_switcher_disable();
+               ret = 0;
+               break;
+       case '1':
+               ret = bL_switcher_enable();
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return (ret >= 0) ? count : ret;
+}
+
+static ssize_t bL_switcher_trace_trigger_store(struct kobject *kobj,
+               struct kobj_attribute *attr, const char *buf, size_t count)
+{
+       int ret = bL_switcher_trace_trigger();
+
+       return ret ? ret : count;
+}
+
+static struct kobj_attribute bL_switcher_active_attr =
+       __ATTR(active, 0644, bL_switcher_active_show, bL_switcher_active_store);
+
+static struct kobj_attribute bL_switcher_trace_trigger_attr =
+       __ATTR(trace_trigger, 0200, NULL, bL_switcher_trace_trigger_store);
+
+static struct attribute *bL_switcher_attrs[] = {
+       &bL_switcher_active_attr.attr,
+       &bL_switcher_trace_trigger_attr.attr,
+       NULL,
+};
+
+static struct attribute_group bL_switcher_attr_group = {
+       .attrs = bL_switcher_attrs,
+};
+
+static struct kobject *bL_switcher_kobj;
+
+static int __init bL_switcher_sysfs_init(void)
+{
+       int ret;
+
+       bL_switcher_kobj = kobject_create_and_add("bL_switcher", kernel_kobj);
+       if (!bL_switcher_kobj)
+               return -ENOMEM;
+       ret = sysfs_create_group(bL_switcher_kobj, &bL_switcher_attr_group);
+       if (ret)
+               kobject_put(bL_switcher_kobj);
+       return ret;
+}
+
+#endif  /* CONFIG_SYSFS */
+
+bool bL_switcher_get_enabled(void)
+{
+       mutex_lock(&bL_switcher_activation_lock);
+
+       return bL_switcher_active;
+}
+EXPORT_SYMBOL_GPL(bL_switcher_get_enabled);
+
+void bL_switcher_put_enabled(void)
+{
+       mutex_unlock(&bL_switcher_activation_lock);
+}
+EXPORT_SYMBOL_GPL(bL_switcher_put_enabled);
+
+/*
+ * Veto any CPU hotplug operation on those CPUs we've removed
+ * while the switcher is active.
+ * We're just not ready to deal with that given the trickery involved.
+ */
+static int bL_switcher_hotplug_callback(struct notifier_block *nfb,
+                                       unsigned long action, void *hcpu)
+{
+       if (bL_switcher_active) {
+               int pairing = bL_switcher_cpu_pairing[(unsigned long)hcpu];
+               switch (action & 0xf) {
+               case CPU_UP_PREPARE:
+               case CPU_DOWN_PREPARE:
+                       if (pairing == -1)
+                               return NOTIFY_BAD;
+               }
+       }
+       return NOTIFY_DONE;
+}
+
+static bool no_bL_switcher;
+core_param(no_bL_switcher, no_bL_switcher, bool, 0644);
+
+static int __init bL_switcher_init(void)
+{
+       int ret;
+
+       if (MAX_NR_CLUSTERS != 2) {
+               pr_err("%s: only dual cluster systems are supported\n", __func__);
+               return -EINVAL;
+       }
+
+       cpu_notifier(bL_switcher_hotplug_callback, 0);
+
+       if (!no_bL_switcher) {
+               ret = bL_switcher_enable();
+               if (ret)
+                       return ret;
+       }
+
+#ifdef CONFIG_SYSFS
+       ret = bL_switcher_sysfs_init();
+       if (ret)
+               pr_err("%s: unable to create sysfs entry\n", __func__);
+#endif
+
+       return 0;
+}
+
+late_initcall(bL_switcher_init);
diff --git a/arch/arm/common/bL_switcher_dummy_if.c b/arch/arm/common/bL_switcher_dummy_if.c
new file mode 100644 (file)
index 0000000..3f47f12
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * arch/arm/common/bL_switcher_dummy_if.c -- b.L switcher dummy interface
+ *
+ * Created by: Nicolas Pitre, November 2012
+ * Copyright:  (C) 2012-2013  Linaro Limited
+ *
+ * Dummy interface to user space for debugging purpose only.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+#include <asm/bL_switcher.h>
+
+static ssize_t bL_switcher_write(struct file *file, const char __user *buf,
+                       size_t len, loff_t *pos)
+{
+       unsigned char val[3];
+       unsigned int cpu, cluster;
+       int ret;
+
+       pr_debug("%s\n", __func__);
+
+       if (len < 3)
+               return -EINVAL;
+
+       if (copy_from_user(val, buf, 3))
+               return -EFAULT;
+
+       /* format: <cpu#>,<cluster#> */
+       if (val[0] < '0' || val[0] > '9' ||
+           val[1] != ',' ||
+           val[2] < '0' || val[2] > '1')
+               return -EINVAL;
+
+       cpu = val[0] - '0';
+       cluster = val[2] - '0';
+       ret = bL_switch_request(cpu, cluster);
+
+       return ret ? : len;
+}
+
+static const struct file_operations bL_switcher_fops = {
+       .write          = bL_switcher_write,
+       .owner  = THIS_MODULE,
+};
+
+static struct miscdevice bL_switcher_device = {
+       MISC_DYNAMIC_MINOR,
+       "b.L_switcher",
+       &bL_switcher_fops
+};
+
+static int __init bL_switcher_dummy_if_init(void)
+{
+       return misc_register(&bL_switcher_device);
+}
+
+static void __exit bL_switcher_dummy_if_exit(void)
+{
+       misc_deregister(&bL_switcher_device);
+}
+
+module_init(bL_switcher_dummy_if_init);
+module_exit(bL_switcher_dummy_if_exit);
index 117f955a2a063b7e57cbbd0a05806ce3413814a7..8e1a0245907f85be1a460bfa785f744daf285d6f 100644 (file)
@@ -269,6 +269,11 @@ static const struct edmacc_param dummy_paramset = {
        .ccnt = 1,
 };
 
+static const struct of_device_id edma_of_ids[] = {
+       { .compatible = "ti,edma3", },
+       {}
+};
+
 /*****************************************************************************/
 
 static void map_dmach_queue(unsigned ctlr, unsigned ch_no,
@@ -560,14 +565,38 @@ static int reserve_contiguous_slots(int ctlr, unsigned int id,
 static int prepare_unused_channel_list(struct device *dev, void *data)
 {
        struct platform_device *pdev = to_platform_device(dev);
-       int i, ctlr;
+       int i, count, ctlr;
+       struct of_phandle_args  dma_spec;
 
+       if (dev->of_node) {
+               count = of_property_count_strings(dev->of_node, "dma-names");
+               if (count < 0)
+                       return 0;
+               for (i = 0; i < count; i++) {
+                       if (of_parse_phandle_with_args(dev->of_node, "dmas",
+                                                      "#dma-cells", i,
+                                                      &dma_spec))
+                               continue;
+
+                       if (!of_match_node(edma_of_ids, dma_spec.np)) {
+                               of_node_put(dma_spec.np);
+                               continue;
+                       }
+
+                       clear_bit(EDMA_CHAN_SLOT(dma_spec.args[0]),
+                                 edma_cc[0]->edma_unused);
+                       of_node_put(dma_spec.np);
+               }
+               return 0;
+       }
+
+       /* For non-OF case */
        for (i = 0; i < pdev->num_resources; i++) {
                if ((pdev->resource[i].flags & IORESOURCE_DMA) &&
                                (int)pdev->resource[i].start >= 0) {
                        ctlr = EDMA_CTLR(pdev->resource[i].start);
                        clear_bit(EDMA_CHAN_SLOT(pdev->resource[i].start),
-                                       edma_cc[ctlr]->edma_unused);
+                                 edma_cc[ctlr]->edma_unused);
                }
        }
 
@@ -1762,11 +1791,6 @@ static int edma_probe(struct platform_device *pdev)
        return 0;
 }
 
-static const struct of_device_id edma_of_ids[] = {
-       { .compatible = "ti,edma3", },
-       {}
-};
-
 static struct platform_driver edma_driver = {
        .driver = {
                .name   = "edma",
index 990250965f2cfb4e4e3a984678fcf62eedbcdb8d..24a9804b8f5e062613532c8a678b1b826b9e7620 100644 (file)
@@ -27,6 +27,18 @@ void mcpm_set_entry_vector(unsigned cpu, unsigned cluster, void *ptr)
        sync_cache_w(&mcpm_entry_vectors[cluster][cpu]);
 }
 
+extern unsigned long mcpm_entry_early_pokes[MAX_NR_CLUSTERS][MAX_CPUS_PER_CLUSTER][2];
+
+void mcpm_set_early_poke(unsigned cpu, unsigned cluster,
+                        unsigned long poke_phys_addr, unsigned long poke_val)
+{
+       unsigned long *poke = &mcpm_entry_early_pokes[cluster][cpu][0];
+       poke[0] = poke_phys_addr;
+       poke[1] = poke_val;
+       __cpuc_flush_dcache_area((void *)poke, 8);
+       outer_clean_range(__pa(poke), __pa(poke + 2));
+}
+
 static const struct mcpm_platform_ops *platform_ops;
 
 int __init mcpm_platform_register(const struct mcpm_platform_ops *ops)
index 39c96df3477a41549d71e1a18733dd85f4a168df..49dd5352fe70336ff023d3c40097a03d4370902f 100644 (file)
@@ -71,12 +71,19 @@ ENTRY(mcpm_entry_point)
         * position independent way.
         */
        adr     r5, 3f
-       ldmia   r5, {r6, r7, r8, r11}
+       ldmia   r5, {r0, r6, r7, r8, r11}
+       add     r0, r5, r0                      @ r0 = mcpm_entry_early_pokes
        add     r6, r5, r6                      @ r6 = mcpm_entry_vectors
        ldr     r7, [r5, r7]                    @ r7 = mcpm_power_up_setup_phys
        add     r8, r5, r8                      @ r8 = mcpm_sync
        add     r11, r5, r11                    @ r11 = first_man_locks
 
+       @ Perform an early poke, if any
+       add     r0, r0, r4, lsl #3
+       ldmia   r0, {r0, r1}
+       teq     r0, #0
+       strne   r1, [r0]
+
        mov     r0, #MCPM_SYNC_CLUSTER_SIZE
        mla     r8, r0, r10, r8                 @ r8 = sync cluster base
 
@@ -195,7 +202,8 @@ mcpm_entry_gated:
 
        .align  2
 
-3:     .word   mcpm_entry_vectors - .
+3:     .word   mcpm_entry_early_pokes - .
+       .word   mcpm_entry_vectors - 3b
        .word   mcpm_power_up_setup_phys - 3b
        .word   mcpm_sync - 3b
        .word   first_man_locks - 3b
@@ -214,6 +222,10 @@ first_man_locks:
 ENTRY(mcpm_entry_vectors)
        .space  4 * MAX_NR_CLUSTERS * MAX_CPUS_PER_CLUSTER
 
+       .type   mcpm_entry_early_pokes, #object
+ENTRY(mcpm_entry_early_pokes)
+       .space  8 * MAX_NR_CLUSTERS * MAX_CPUS_PER_CLUSTER
+
        .type   mcpm_power_up_setup_phys, #object
 ENTRY(mcpm_power_up_setup_phys)
        .space  4               @ set by mcpm_sync_init()
index e901d0f3e0bbcd735f5cf7e62bd653536ff8aa71..ce922d0ea7aa85daa59c408ac5cd79beab5459a6 100644 (file)
@@ -175,7 +175,7 @@ static struct clock_event_device sp804_clockevent = {
 
 static struct irqaction sp804_timer_irq = {
        .name           = "timer",
-       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+       .flags          = IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = sp804_timer_interrupt,
        .dev_id         = &sp804_clockevent,
 };
index 317960f1248893d6200650ec9c01e8132b627c16..0142ec37e0be26d8c1480aa4929a722896b3b397 100644 (file)
@@ -1,5 +1,6 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_MODULES=y
@@ -11,11 +12,11 @@ CONFIG_ARCH_SA1100=y
 CONFIG_SA1100_H3600=y
 CONFIG_PCCARD=y
 CONFIG_PCMCIA_SA1100=y
+CONFIG_PREEMPT=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 # CONFIG_CPU_FREQ_STAT is not set
 CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
@@ -24,13 +25,10 @@ CONFIG_IRDA=m
 CONFIG_IRLAN=m
 CONFIG_IRNET=m
 CONFIG_IRCOMM=m
-CONFIG_SA1100_FIR=m
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_ADV_OPTIONS=y
@@ -41,19 +39,15 @@ CONFIG_MTD_SA1100=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
-# CONFIG_MISC_DEVICES is not set
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECS=y
 CONFIG_NETDEVICES=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_WLAN is not set
-CONFIG_NET_PCMCIA=y
 CONFIG_PCMCIA_PCNET=y
 CONFIG_PPP=m
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_ASYNC=m
+# CONFIG_WLAN is not set
 # CONFIG_KEYBOARD_ATKBD is not set
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
@@ -64,8 +58,6 @@ CONFIG_SERIAL_SA1100_CONSOLE=y
 # CONFIG_HWMON is not set
 CONFIG_FB=y
 CONFIG_FB_SA1100=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_EXT2_FS=y
 CONFIG_MSDOS_FS=m
@@ -74,6 +66,4 @@ CONFIG_JFFS2_FS=y
 CONFIG_CRAMFS=m
 CONFIG_NFS_FS=y
 CONFIG_NFSD=m
-CONFIG_SMB_FS=m
 CONFIG_NLS=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
index 6e572c64cf5a1258008232a002301ab7925b0911..119fc378fc520f8ae5cb9074686570b6436bcd93 100644 (file)
@@ -36,6 +36,7 @@ CONFIG_ARCH_TEGRA_114_SOC=y
 CONFIG_TEGRA_PCI=y
 CONFIG_TEGRA_EMC_SCALING_ENABLE=y
 CONFIG_ARCH_U8500=y
+CONFIG_MACH_HREFV60=y
 CONFIG_MACH_SNOWBALL=y
 CONFIG_MACH_UX500_DT=y
 CONFIG_ARCH_VEXPRESS=y
@@ -46,6 +47,7 @@ CONFIG_ARCH_ZYNQ=y
 CONFIG_SMP=y
 CONFIG_HIGHPTE=y
 CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
 CONFIG_NET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
@@ -133,6 +135,7 @@ CONFIG_MMC=y
 CONFIG_MMC_ARMMMCI=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
 CONFIG_MMC_SDHCI_TEGRA=y
 CONFIG_MMC_SDHCI_SPEAR=y
 CONFIG_MMC_OMAP=y
diff --git a/arch/arm/crypto/.gitignore b/arch/arm/crypto/.gitignore
new file mode 100644 (file)
index 0000000..6231d36
--- /dev/null
@@ -0,0 +1 @@
+aesbs-core.S
index a2c83851bc90a29f5f1d06415cb4a0db4dd726e1..81cda39860c5c7ad90a6710727011ec79296e5d8 100644 (file)
@@ -3,7 +3,17 @@
 #
 
 obj-$(CONFIG_CRYPTO_AES_ARM) += aes-arm.o
+obj-$(CONFIG_CRYPTO_AES_ARM_BS) += aes-arm-bs.o
 obj-$(CONFIG_CRYPTO_SHA1_ARM) += sha1-arm.o
 
-aes-arm-y  := aes-armv4.o aes_glue.o
-sha1-arm-y := sha1-armv4-large.o sha1_glue.o
+aes-arm-y      := aes-armv4.o aes_glue.o
+aes-arm-bs-y   := aesbs-core.o aesbs-glue.o
+sha1-arm-y     := sha1-armv4-large.o sha1_glue.o
+
+quiet_cmd_perl = PERL    $@
+      cmd_perl = $(PERL) $(<) > $(@)
+
+$(src)/aesbs-core.S_shipped: $(src)/bsaes-armv7.pl
+       $(call cmd,perl)
+
+.PRECIOUS: $(obj)/aesbs-core.S
index 59f7877ead6ac9ee3f8a31b43c6e0458de26cd8f..3003fa1f6fb4b9395c77340fbf83011b5cb0e419 100644 (file)
@@ -6,22 +6,12 @@
 #include <linux/crypto.h>
 #include <crypto/aes.h>
 
-#define AES_MAXNR 14
+#include "aes_glue.h"
 
-typedef struct {
-       unsigned int rd_key[4 *(AES_MAXNR + 1)];
-       int rounds;
-} AES_KEY;
-
-struct AES_CTX {
-       AES_KEY enc_key;
-       AES_KEY dec_key;
-};
-
-asmlinkage void AES_encrypt(const u8 *in, u8 *out, AES_KEY *ctx);
-asmlinkage void AES_decrypt(const u8 *in, u8 *out, AES_KEY *ctx);
-asmlinkage int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);
-asmlinkage int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);
+EXPORT_SYMBOL(AES_encrypt);
+EXPORT_SYMBOL(AES_decrypt);
+EXPORT_SYMBOL(private_AES_set_encrypt_key);
+EXPORT_SYMBOL(private_AES_set_decrypt_key);
 
 static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
@@ -81,7 +71,7 @@ static struct crypto_alg aes_alg = {
                .cipher = {
                        .cia_min_keysize        = AES_MIN_KEY_SIZE,
                        .cia_max_keysize        = AES_MAX_KEY_SIZE,
-                       .cia_setkey                     = aes_set_key,
+                       .cia_setkey             = aes_set_key,
                        .cia_encrypt            = aes_encrypt,
                        .cia_decrypt            = aes_decrypt
                }
diff --git a/arch/arm/crypto/aes_glue.h b/arch/arm/crypto/aes_glue.h
new file mode 100644 (file)
index 0000000..cca3e51
--- /dev/null
@@ -0,0 +1,19 @@
+
+#define AES_MAXNR 14
+
+struct AES_KEY {
+       unsigned int rd_key[4 * (AES_MAXNR + 1)];
+       int rounds;
+};
+
+struct AES_CTX {
+       struct AES_KEY enc_key;
+       struct AES_KEY dec_key;
+};
+
+asmlinkage void AES_encrypt(const u8 *in, u8 *out, struct AES_KEY *ctx);
+asmlinkage void AES_decrypt(const u8 *in, u8 *out, struct AES_KEY *ctx);
+asmlinkage int private_AES_set_decrypt_key(const unsigned char *userKey,
+                                          const int bits, struct AES_KEY *key);
+asmlinkage int private_AES_set_encrypt_key(const unsigned char *userKey,
+                                          const int bits, struct AES_KEY *key);
diff --git a/arch/arm/crypto/aesbs-core.S_shipped b/arch/arm/crypto/aesbs-core.S_shipped
new file mode 100644 (file)
index 0000000..64205d4
--- /dev/null
@@ -0,0 +1,2544 @@
+
+@ ====================================================================
+@ Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+@ project. The module is, however, dual licensed under OpenSSL and
+@ CRYPTOGAMS licenses depending on where you obtain it. For further
+@ details see http://www.openssl.org/~appro/cryptogams/.
+@
+@ Specific modes and adaptation for Linux kernel by Ard Biesheuvel
+@ <ard.biesheuvel@linaro.org>. Permission to use under GPL terms is
+@ granted.
+@ ====================================================================
+
+@ Bit-sliced AES for ARM NEON
+@
+@ February 2012.
+@
+@ This implementation is direct adaptation of bsaes-x86_64 module for
+@ ARM NEON. Except that this module is endian-neutral [in sense that
+@ it can be compiled for either endianness] by courtesy of vld1.8's
+@ neutrality. Initial version doesn't implement interface to OpenSSL,
+@ only low-level primitives and unsupported entry points, just enough
+@ to collect performance results, which for Cortex-A8 core are:
+@
+@ encrypt      19.5 cycles per byte processed with 128-bit key
+@ decrypt      22.1 cycles per byte processed with 128-bit key
+@ key conv.    440  cycles per 128-bit key/0.18 of 8x block
+@
+@ Snapdragon S4 encrypts byte in 17.6 cycles and decrypts in 19.7,
+@ which is [much] worse than anticipated (for further details see
+@ http://www.openssl.org/~appro/Snapdragon-S4.html).
+@
+@ Cortex-A15 manages in 14.2/16.1 cycles [when integer-only code
+@ manages in 20.0 cycles].
+@
+@ When comparing to x86_64 results keep in mind that NEON unit is
+@ [mostly] single-issue and thus can't [fully] benefit from
+@ instruction-level parallelism. And when comparing to aes-armv4
+@ results keep in mind key schedule conversion overhead (see
+@ bsaes-x86_64.pl for further details)...
+@
+@                                              <appro@openssl.org>
+
+@ April-August 2013
+@
+@ Add CBC, CTR and XTS subroutines, adapt for kernel use.
+@
+@                                      <ard.biesheuvel@linaro.org>
+
+#ifndef __KERNEL__
+# include "arm_arch.h"
+
+# define VFP_ABI_PUSH  vstmdb  sp!,{d8-d15}
+# define VFP_ABI_POP   vldmia  sp!,{d8-d15}
+# define VFP_ABI_FRAME 0x40
+#else
+# define VFP_ABI_PUSH
+# define VFP_ABI_POP
+# define VFP_ABI_FRAME 0
+# define BSAES_ASM_EXTENDED_KEY
+# define XTS_CHAIN_TWEAK
+# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+#endif
+
+#ifdef __thumb__
+# define adrl adr
+#endif
+
+#if __ARM_ARCH__>=7
+.text
+.syntax        unified         @ ARMv7-capable assembler is expected to handle this
+#ifdef __thumb2__
+.thumb
+#else
+.code   32
+#endif
+
+.fpu   neon
+
+.type  _bsaes_decrypt8,%function
+.align 4
+_bsaes_decrypt8:
+       adr     r6,_bsaes_decrypt8
+       vldmia  r4!, {q9}               @ round 0 key
+       add     r6,r6,#.LM0ISR-_bsaes_decrypt8
+
+       vldmia  r6!, {q8}               @ .LM0ISR
+       veor    q10, q0, q9     @ xor with round0 key
+       veor    q11, q1, q9
+        vtbl.8 d0, {q10}, d16
+        vtbl.8 d1, {q10}, d17
+       veor    q12, q2, q9
+        vtbl.8 d2, {q11}, d16
+        vtbl.8 d3, {q11}, d17
+       veor    q13, q3, q9
+        vtbl.8 d4, {q12}, d16
+        vtbl.8 d5, {q12}, d17
+       veor    q14, q4, q9
+        vtbl.8 d6, {q13}, d16
+        vtbl.8 d7, {q13}, d17
+       veor    q15, q5, q9
+        vtbl.8 d8, {q14}, d16
+        vtbl.8 d9, {q14}, d17
+       veor    q10, q6, q9
+        vtbl.8 d10, {q15}, d16
+        vtbl.8 d11, {q15}, d17
+       veor    q11, q7, q9
+        vtbl.8 d12, {q10}, d16
+        vtbl.8 d13, {q10}, d17
+        vtbl.8 d14, {q11}, d16
+        vtbl.8 d15, {q11}, d17
+       vmov.i8 q8,#0x55                        @ compose .LBS0
+       vmov.i8 q9,#0x33                        @ compose .LBS1
+       vshr.u64        q10, q6, #1
+        vshr.u64       q11, q4, #1
+       veor            q10, q10, q7
+        veor           q11, q11, q5
+       vand            q10, q10, q8
+        vand           q11, q11, q8
+       veor            q7, q7, q10
+       vshl.u64        q10, q10, #1
+        veor           q5, q5, q11
+        vshl.u64       q11, q11, #1
+       veor            q6, q6, q10
+        veor           q4, q4, q11
+       vshr.u64        q10, q2, #1
+        vshr.u64       q11, q0, #1
+       veor            q10, q10, q3
+        veor           q11, q11, q1
+       vand            q10, q10, q8
+        vand           q11, q11, q8
+       veor            q3, q3, q10
+       vshl.u64        q10, q10, #1
+        veor           q1, q1, q11
+        vshl.u64       q11, q11, #1
+       veor            q2, q2, q10
+        veor           q0, q0, q11
+       vmov.i8 q8,#0x0f                        @ compose .LBS2
+       vshr.u64        q10, q5, #2
+        vshr.u64       q11, q4, #2
+       veor            q10, q10, q7
+        veor           q11, q11, q6
+       vand            q10, q10, q9
+        vand           q11, q11, q9
+       veor            q7, q7, q10
+       vshl.u64        q10, q10, #2
+        veor           q6, q6, q11
+        vshl.u64       q11, q11, #2
+       veor            q5, q5, q10
+        veor           q4, q4, q11
+       vshr.u64        q10, q1, #2
+        vshr.u64       q11, q0, #2
+       veor            q10, q10, q3
+        veor           q11, q11, q2
+       vand            q10, q10, q9
+        vand           q11, q11, q9
+       veor            q3, q3, q10
+       vshl.u64        q10, q10, #2
+        veor           q2, q2, q11
+        vshl.u64       q11, q11, #2
+       veor            q1, q1, q10
+        veor           q0, q0, q11
+       vshr.u64        q10, q3, #4
+        vshr.u64       q11, q2, #4
+       veor            q10, q10, q7
+        veor           q11, q11, q6
+       vand            q10, q10, q8
+        vand           q11, q11, q8
+       veor            q7, q7, q10
+       vshl.u64        q10, q10, #4
+        veor           q6, q6, q11
+        vshl.u64       q11, q11, #4
+       veor            q3, q3, q10
+        veor           q2, q2, q11
+       vshr.u64        q10, q1, #4
+        vshr.u64       q11, q0, #4
+       veor            q10, q10, q5
+        veor           q11, q11, q4
+       vand            q10, q10, q8
+        vand           q11, q11, q8
+       veor            q5, q5, q10
+       vshl.u64        q10, q10, #4
+        veor           q4, q4, q11
+        vshl.u64       q11, q11, #4
+       veor            q1, q1, q10
+        veor           q0, q0, q11
+       sub     r5,r5,#1
+       b       .Ldec_sbox
+.align 4
+.Ldec_loop:
+       vldmia  r4!, {q8-q11}
+       veor    q8, q8, q0
+       veor    q9, q9, q1
+       vtbl.8  d0, {q8}, d24
+       vtbl.8  d1, {q8}, d25
+       vldmia  r4!, {q8}
+       veor    q10, q10, q2
+       vtbl.8  d2, {q9}, d24
+       vtbl.8  d3, {q9}, d25
+       vldmia  r4!, {q9}
+       veor    q11, q11, q3
+       vtbl.8  d4, {q10}, d24
+       vtbl.8  d5, {q10}, d25
+       vldmia  r4!, {q10}
+       vtbl.8  d6, {q11}, d24
+       vtbl.8  d7, {q11}, d25
+       vldmia  r4!, {q11}
+       veor    q8, q8, q4
+       veor    q9, q9, q5
+       vtbl.8  d8, {q8}, d24
+       vtbl.8  d9, {q8}, d25
+       veor    q10, q10, q6
+       vtbl.8  d10, {q9}, d24
+       vtbl.8  d11, {q9}, d25
+       veor    q11, q11, q7
+       vtbl.8  d12, {q10}, d24
+       vtbl.8  d13, {q10}, d25
+       vtbl.8  d14, {q11}, d24
+       vtbl.8  d15, {q11}, d25
+.Ldec_sbox:
+        veor   q1, q1, q4
+       veor    q3, q3, q4
+
+       veor    q4, q4, q7
+        veor   q1, q1, q6
+       veor    q2, q2, q7
+       veor    q6, q6, q4
+
+       veor    q0, q0, q1
+       veor    q2, q2, q5
+        veor   q7, q7, q6
+       veor    q3, q3, q0
+       veor    q5, q5, q0
+       veor    q1, q1, q3
+       veor    q11, q3, q0
+       veor    q10, q7, q4
+       veor    q9, q1, q6
+       veor    q13, q4, q0
+        vmov   q8, q10
+       veor    q12, q5, q2
+
+       vorr    q10, q10, q9
+       veor    q15, q11, q8
+       vand    q14, q11, q12
+       vorr    q11, q11, q12
+       veor    q12, q12, q9
+       vand    q8, q8, q9
+       veor    q9, q6, q2
+       vand    q15, q15, q12
+       vand    q13, q13, q9
+       veor    q9, q3, q7
+       veor    q12, q1, q5
+       veor    q11, q11, q13
+       veor    q10, q10, q13
+       vand    q13, q9, q12
+       vorr    q9, q9, q12
+       veor    q11, q11, q15
+       veor    q8, q8, q13
+       veor    q10, q10, q14
+       veor    q9, q9, q15
+       veor    q8, q8, q14
+       vand    q12, q4, q6
+       veor    q9, q9, q14
+       vand    q13, q0, q2
+       vand    q14, q7, q1
+       vorr    q15, q3, q5
+       veor    q11, q11, q12
+       veor    q9, q9, q14
+       veor    q8, q8, q15
+       veor    q10, q10, q13
+
+       @ Inv_GF16      0,      1,      2,      3, s0, s1, s2, s3
+
+       @ new smaller inversion
+
+       vand    q14, q11, q9
+       vmov    q12, q8
+
+       veor    q13, q10, q14
+       veor    q15, q8, q14
+       veor    q14, q8, q14    @ q14=q15
+
+       vbsl    q13, q9, q8
+       vbsl    q15, q11, q10
+       veor    q11, q11, q10
+
+       vbsl    q12, q13, q14
+       vbsl    q8, q14, q13
+
+       vand    q14, q12, q15
+       veor    q9, q9, q8
+
+       veor    q14, q14, q11
+       veor    q12, q5, q2
+       veor    q8, q1, q6
+       veor    q10, q15, q14
+       vand    q10, q10, q5
+       veor    q5, q5, q1
+       vand    q11, q1, q15
+       vand    q5, q5, q14
+       veor    q1, q11, q10
+       veor    q5, q5, q11
+       veor    q15, q15, q13
+       veor    q14, q14, q9
+       veor    q11, q15, q14
+        veor   q10, q13, q9
+       vand    q11, q11, q12
+        vand   q10, q10, q2
+       veor    q12, q12, q8
+        veor   q2, q2, q6
+       vand    q8, q8, q15
+        vand   q6, q6, q13
+       vand    q12, q12, q14
+        vand   q2, q2, q9
+       veor    q8, q8, q12
+        veor   q2, q2, q6
+       veor    q12, q12, q11
+        veor   q6, q6, q10
+       veor    q5, q5, q12
+       veor    q2, q2, q12
+       veor    q1, q1, q8
+       veor    q6, q6, q8
+
+       veor    q12, q3, q0
+       veor    q8, q7, q4
+       veor    q11, q15, q14
+        veor   q10, q13, q9
+       vand    q11, q11, q12
+        vand   q10, q10, q0
+       veor    q12, q12, q8
+        veor   q0, q0, q4
+       vand    q8, q8, q15
+        vand   q4, q4, q13
+       vand    q12, q12, q14
+        vand   q0, q0, q9
+       veor    q8, q8, q12
+        veor   q0, q0, q4
+       veor    q12, q12, q11
+        veor   q4, q4, q10
+       veor    q15, q15, q13
+       veor    q14, q14, q9
+       veor    q10, q15, q14
+       vand    q10, q10, q3
+       veor    q3, q3, q7
+       vand    q11, q7, q15
+       vand    q3, q3, q14
+       veor    q7, q11, q10
+       veor    q3, q3, q11
+       veor    q3, q3, q12
+       veor    q0, q0, q12
+       veor    q7, q7, q8
+       veor    q4, q4, q8
+       veor    q1, q1, q7
+       veor    q6, q6, q5
+
+       veor    q4, q4, q1
+       veor    q2, q2, q7
+       veor    q5, q5, q7
+       veor    q4, q4, q2
+        veor   q7, q7, q0
+       veor    q4, q4, q5
+        veor   q3, q3, q6
+        veor   q6, q6, q1
+       veor    q3, q3, q4
+
+       veor    q4, q4, q0
+       veor    q7, q7, q3
+       subs    r5,r5,#1
+       bcc     .Ldec_done
+       @ multiplication by 0x05-0x00-0x04-0x00
+       vext.8  q8, q0, q0, #8
+       vext.8  q14, q3, q3, #8
+       vext.8  q15, q5, q5, #8
+       veor    q8, q8, q0
+       vext.8  q9, q1, q1, #8
+       veor    q14, q14, q3
+       vext.8  q10, q6, q6, #8
+       veor    q15, q15, q5
+       vext.8  q11, q4, q4, #8
+       veor    q9, q9, q1
+       vext.8  q12, q2, q2, #8
+       veor    q10, q10, q6
+       vext.8  q13, q7, q7, #8
+       veor    q11, q11, q4
+       veor    q12, q12, q2
+       veor    q13, q13, q7
+
+        veor   q0, q0, q14
+        veor   q1, q1, q14
+        veor   q6, q6, q8
+        veor   q2, q2, q10
+        veor   q4, q4, q9
+        veor   q1, q1, q15
+        veor   q6, q6, q15
+        veor   q2, q2, q14
+        veor   q7, q7, q11
+        veor   q4, q4, q14
+        veor   q3, q3, q12
+        veor   q2, q2, q15
+        veor   q7, q7, q15
+        veor   q5, q5, q13
+       vext.8  q8, q0, q0, #12 @ x0 <<< 32
+       vext.8  q9, q1, q1, #12
+        veor   q0, q0, q8              @ x0 ^ (x0 <<< 32)
+       vext.8  q10, q6, q6, #12
+        veor   q1, q1, q9
+       vext.8  q11, q4, q4, #12
+        veor   q6, q6, q10
+       vext.8  q12, q2, q2, #12
+        veor   q4, q4, q11
+       vext.8  q13, q7, q7, #12
+        veor   q2, q2, q12
+       vext.8  q14, q3, q3, #12
+        veor   q7, q7, q13
+       vext.8  q15, q5, q5, #12
+        veor   q3, q3, q14
+
+       veor    q9, q9, q0
+        veor   q5, q5, q15
+        vext.8 q0, q0, q0, #8          @ (x0 ^ (x0 <<< 32)) <<< 64)
+       veor    q10, q10, q1
+       veor    q8, q8, q5
+       veor    q9, q9, q5
+        vext.8 q1, q1, q1, #8
+       veor    q13, q13, q2
+        veor   q0, q0, q8
+       veor    q14, q14, q7
+        veor   q1, q1, q9
+        vext.8 q8, q2, q2, #8
+       veor    q12, q12, q4
+        vext.8 q9, q7, q7, #8
+       veor    q15, q15, q3
+        vext.8 q2, q4, q4, #8
+       veor    q11, q11, q6
+        vext.8 q7, q5, q5, #8
+       veor    q12, q12, q5
+        vext.8 q4, q3, q3, #8
+       veor    q11, q11, q5
+        vext.8 q3, q6, q6, #8
+       veor    q5, q9, q13
+       veor    q11, q11, q2
+       veor    q7, q7, q15
+       veor    q6, q4, q14
+       veor    q4, q8, q12
+       veor    q2, q3, q10
+       vmov    q3, q11
+        @ vmov q5, q9
+       vldmia  r6, {q12}               @ .LISR
+       ite     eq                              @ Thumb2 thing, sanity check in ARM
+       addeq   r6,r6,#0x10
+       bne     .Ldec_loop
+       vldmia  r6, {q12}               @ .LISRM0
+       b       .Ldec_loop
+.align 4
+.Ldec_done:
+       vmov.i8 q8,#0x55                        @ compose .LBS0
+       vmov.i8 q9,#0x33                        @ compose .LBS1
+       vshr.u64        q10, q3, #1
+        vshr.u64       q11, q2, #1
+       veor            q10, q10, q5
+        veor           q11, q11, q7
+       vand            q10, q10, q8
+        vand           q11, q11, q8
+       veor            q5, q5, q10
+       vshl.u64        q10, q10, #1
+        veor           q7, q7, q11
+        vshl.u64       q11, q11, #1
+       veor            q3, q3, q10
+        veor           q2, q2, q11
+       vshr.u64        q10, q6, #1
+        vshr.u64       q11, q0, #1
+       veor            q10, q10, q4
+        veor           q11, q11, q1
+       vand            q10, q10, q8
+        vand           q11, q11, q8
+       veor            q4, q4, q10
+       vshl.u64        q10, q10, #1
+        veor           q1, q1, q11
+        vshl.u64       q11, q11, #1
+       veor            q6, q6, q10
+        veor           q0, q0, q11
+       vmov.i8 q8,#0x0f                        @ compose .LBS2
+       vshr.u64        q10, q7, #2
+        vshr.u64       q11, q2, #2
+       veor            q10, q10, q5
+        veor           q11, q11, q3
+       vand            q10, q10, q9
+        vand           q11, q11, q9
+       veor            q5, q5, q10
+       vshl.u64        q10, q10, #2
+        veor           q3, q3, q11
+        vshl.u64       q11, q11, #2
+       veor            q7, q7, q10
+        veor           q2, q2, q11
+       vshr.u64        q10, q1, #2
+        vshr.u64       q11, q0, #2
+       veor            q10, q10, q4
+        veor           q11, q11, q6
+       vand            q10, q10, q9
+        vand           q11, q11, q9
+       veor            q4, q4, q10
+       vshl.u64        q10, q10, #2
+        veor           q6, q6, q11
+        vshl.u64       q11, q11, #2
+       veor            q1, q1, q10
+        veor           q0, q0, q11
+       vshr.u64        q10, q4, #4
+        vshr.u64       q11, q6, #4
+       veor            q10, q10, q5
+        veor           q11, q11, q3
+       vand            q10, q10, q8
+        vand           q11, q11, q8
+       veor            q5, q5, q10
+       vshl.u64        q10, q10, #4
+        veor           q3, q3, q11
+        vshl.u64       q11, q11, #4
+       veor            q4, q4, q10
+        veor           q6, q6, q11
+       vshr.u64        q10, q1, #4
+        vshr.u64       q11, q0, #4
+       veor            q10, q10, q7
+        veor           q11, q11, q2
+       vand            q10, q10, q8
+        vand           q11, q11, q8
+       veor            q7, q7, q10
+       vshl.u64        q10, q10, #4
+        veor           q2, q2, q11
+        vshl.u64       q11, q11, #4
+       veor            q1, q1, q10
+        veor           q0, q0, q11
+       vldmia  r4, {q8}                        @ last round key
+       veor    q6, q6, q8
+       veor    q4, q4, q8
+       veor    q2, q2, q8
+       veor    q7, q7, q8
+       veor    q3, q3, q8
+       veor    q5, q5, q8
+       veor    q0, q0, q8
+       veor    q1, q1, q8
+       bx      lr
+.size  _bsaes_decrypt8,.-_bsaes_decrypt8
+
+.type  _bsaes_const,%object
+.align 6
+_bsaes_const:
+.LM0ISR:       @ InvShiftRows constants
+       .quad   0x0a0e0206070b0f03, 0x0004080c0d010509
+.LISR:
+       .quad   0x0504070602010003, 0x0f0e0d0c080b0a09
+.LISRM0:
+       .quad   0x01040b0e0205080f, 0x0306090c00070a0d
+.LM0SR:                @ ShiftRows constants
+       .quad   0x0a0e02060f03070b, 0x0004080c05090d01
+.LSR:
+       .quad   0x0504070600030201, 0x0f0e0d0c0a09080b
+.LSRM0:
+       .quad   0x0304090e00050a0f, 0x01060b0c0207080d
+.LM0:
+       .quad   0x02060a0e03070b0f, 0x0004080c0105090d
+.LREVM0SR:
+       .quad   0x090d01050c000408, 0x03070b0f060a0e02
+.asciz "Bit-sliced AES for NEON, CRYPTOGAMS by <appro@openssl.org>"
+.align 6
+.size  _bsaes_const,.-_bsaes_const
+
+.type  _bsaes_encrypt8,%function
+.align 4
+_bsaes_encrypt8:
+       adr     r6,_bsaes_encrypt8
+       vldmia  r4!, {q9}               @ round 0 key
+       sub     r6,r6,#_bsaes_encrypt8-.LM0SR
+
+       vldmia  r6!, {q8}               @ .LM0SR
+_bsaes_encrypt8_alt:
+       veor    q10, q0, q9     @ xor with round0 key
+       veor    q11, q1, q9
+        vtbl.8 d0, {q10}, d16
+        vtbl.8 d1, {q10}, d17
+       veor    q12, q2, q9
+        vtbl.8 d2, {q11}, d16
+        vtbl.8 d3, {q11}, d17
+       veor    q13, q3, q9
+        vtbl.8 d4, {q12}, d16
+        vtbl.8 d5, {q12}, d17
+       veor    q14, q4, q9
+        vtbl.8 d6, {q13}, d16
+        vtbl.8 d7, {q13}, d17
+       veor    q15, q5, q9
+        vtbl.8 d8, {q14}, d16
+        vtbl.8 d9, {q14}, d17
+       veor    q10, q6, q9
+        vtbl.8 d10, {q15}, d16
+        vtbl.8 d11, {q15}, d17
+       veor    q11, q7, q9
+        vtbl.8 d12, {q10}, d16
+        vtbl.8 d13, {q10}, d17
+        vtbl.8 d14, {q11}, d16
+        vtbl.8 d15, {q11}, d17
+_bsaes_encrypt8_bitslice:
+       vmov.i8 q8,#0x55                        @ compose .LBS0
+       vmov.i8 q9,#0x33                        @ compose .LBS1
+       vshr.u64        q10, q6, #1
+        vshr.u64       q11, q4, #1
+       veor            q10, q10, q7
+        veor           q11, q11, q5
+       vand            q10, q10, q8
+        vand           q11, q11, q8
+       veor            q7, q7, q10
+       vshl.u64        q10, q10, #1
+        veor           q5, q5, q11
+        vshl.u64       q11, q11, #1
+       veor            q6, q6, q10
+        veor           q4, q4, q11
+       vshr.u64        q10, q2, #1
+        vshr.u64       q11, q0, #1
+       veor            q10, q10, q3
+        veor           q11, q11, q1
+       vand            q10, q10, q8
+        vand           q11, q11, q8
+       veor            q3, q3, q10
+       vshl.u64        q10, q10, #1
+        veor           q1, q1, q11
+        vshl.u64       q11, q11, #1
+       veor            q2, q2, q10
+        veor           q0, q0, q11
+       vmov.i8 q8,#0x0f                        @ compose .LBS2
+       vshr.u64        q10, q5, #2
+        vshr.u64       q11, q4, #2
+       veor            q10, q10, q7
+        veor           q11, q11, q6
+       vand            q10, q10, q9
+        vand           q11, q11, q9
+       veor            q7, q7, q10
+       vshl.u64        q10, q10, #2
+        veor           q6, q6, q11
+        vshl.u64       q11, q11, #2
+       veor            q5, q5, q10
+        veor           q4, q4, q11
+       vshr.u64        q10, q1, #2
+        vshr.u64       q11, q0, #2
+       veor            q10, q10, q3
+        veor           q11, q11, q2
+       vand            q10, q10, q9
+        vand           q11, q11, q9
+       veor            q3, q3, q10
+       vshl.u64        q10, q10, #2
+        veor           q2, q2, q11
+        vshl.u64       q11, q11, #2
+       veor            q1, q1, q10
+        veor           q0, q0, q11
+       vshr.u64        q10, q3, #4
+        vshr.u64       q11, q2, #4
+       veor            q10, q10, q7
+        veor           q11, q11, q6
+       vand            q10, q10, q8
+        vand           q11, q11, q8
+       veor            q7, q7, q10
+       vshl.u64        q10, q10, #4
+        veor           q6, q6, q11
+        vshl.u64       q11, q11, #4
+       veor            q3, q3, q10
+        veor           q2, q2, q11
+       vshr.u64        q10, q1, #4
+        vshr.u64       q11, q0, #4
+       veor            q10, q10, q5
+        veor           q11, q11, q4
+       vand            q10, q10, q8
+        vand           q11, q11, q8
+       veor            q5, q5, q10
+       vshl.u64        q10, q10, #4
+        veor           q4, q4, q11
+        vshl.u64       q11, q11, #4
+       veor            q1, q1, q10
+        veor           q0, q0, q11
+       sub     r5,r5,#1
+       b       .Lenc_sbox
+.align 4
+.Lenc_loop:
+       vldmia  r4!, {q8-q11}
+       veor    q8, q8, q0
+       veor    q9, q9, q1
+       vtbl.8  d0, {q8}, d24
+       vtbl.8  d1, {q8}, d25
+       vldmia  r4!, {q8}
+       veor    q10, q10, q2
+       vtbl.8  d2, {q9}, d24
+       vtbl.8  d3, {q9}, d25
+       vldmia  r4!, {q9}
+       veor    q11, q11, q3
+       vtbl.8  d4, {q10}, d24
+       vtbl.8  d5, {q10}, d25
+       vldmia  r4!, {q10}
+       vtbl.8  d6, {q11}, d24
+       vtbl.8  d7, {q11}, d25
+       vldmia  r4!, {q11}
+       veor    q8, q8, q4
+       veor    q9, q9, q5
+       vtbl.8  d8, {q8}, d24
+       vtbl.8  d9, {q8}, d25
+       veor    q10, q10, q6
+       vtbl.8  d10, {q9}, d24
+       vtbl.8  d11, {q9}, d25
+       veor    q11, q11, q7
+       vtbl.8  d12, {q10}, d24
+       vtbl.8  d13, {q10}, d25
+       vtbl.8  d14, {q11}, d24
+       vtbl.8  d15, {q11}, d25
+.Lenc_sbox:
+       veor    q2, q2, q1
+       veor    q5, q5, q6
+       veor    q3, q3, q0
+       veor    q6, q6, q2
+       veor    q5, q5, q0
+
+       veor    q6, q6, q3
+       veor    q3, q3, q7
+       veor    q7, q7, q5
+       veor    q3, q3, q4
+       veor    q4, q4, q5
+
+       veor    q2, q2, q7
+       veor    q3, q3, q1
+       veor    q1, q1, q5
+       veor    q11, q7, q4
+       veor    q10, q1, q2
+       veor    q9, q5, q3
+       veor    q13, q2, q4
+        vmov   q8, q10
+       veor    q12, q6, q0
+
+       vorr    q10, q10, q9
+       veor    q15, q11, q8
+       vand    q14, q11, q12
+       vorr    q11, q11, q12
+       veor    q12, q12, q9
+       vand    q8, q8, q9
+       veor    q9, q3, q0
+       vand    q15, q15, q12
+       vand    q13, q13, q9
+       veor    q9, q7, q1
+       veor    q12, q5, q6
+       veor    q11, q11, q13
+       veor    q10, q10, q13
+       vand    q13, q9, q12
+       vorr    q9, q9, q12
+       veor    q11, q11, q15
+       veor    q8, q8, q13
+       veor    q10, q10, q14
+       veor    q9, q9, q15
+       veor    q8, q8, q14
+       vand    q12, q2, q3
+       veor    q9, q9, q14
+       vand    q13, q4, q0
+       vand    q14, q1, q5
+       vorr    q15, q7, q6
+       veor    q11, q11, q12
+       veor    q9, q9, q14
+       veor    q8, q8, q15
+       veor    q10, q10, q13
+
+       @ Inv_GF16      0,      1,      2,      3, s0, s1, s2, s3
+
+       @ new smaller inversion
+
+       vand    q14, q11, q9
+       vmov    q12, q8
+
+       veor    q13, q10, q14
+       veor    q15, q8, q14
+       veor    q14, q8, q14    @ q14=q15
+
+       vbsl    q13, q9, q8
+       vbsl    q15, q11, q10
+       veor    q11, q11, q10
+
+       vbsl    q12, q13, q14
+       vbsl    q8, q14, q13
+
+       vand    q14, q12, q15
+       veor    q9, q9, q8
+
+       veor    q14, q14, q11
+       veor    q12, q6, q0
+       veor    q8, q5, q3
+       veor    q10, q15, q14
+       vand    q10, q10, q6
+       veor    q6, q6, q5
+       vand    q11, q5, q15
+       vand    q6, q6, q14
+       veor    q5, q11, q10
+       veor    q6, q6, q11
+       veor    q15, q15, q13
+       veor    q14, q14, q9
+       veor    q11, q15, q14
+        veor   q10, q13, q9
+       vand    q11, q11, q12
+        vand   q10, q10, q0
+       veor    q12, q12, q8
+        veor   q0, q0, q3
+       vand    q8, q8, q15
+        vand   q3, q3, q13
+       vand    q12, q12, q14
+        vand   q0, q0, q9
+       veor    q8, q8, q12
+        veor   q0, q0, q3
+       veor    q12, q12, q11
+        veor   q3, q3, q10
+       veor    q6, q6, q12
+       veor    q0, q0, q12
+       veor    q5, q5, q8
+       veor    q3, q3, q8
+
+       veor    q12, q7, q4
+       veor    q8, q1, q2
+       veor    q11, q15, q14
+        veor   q10, q13, q9
+       vand    q11, q11, q12
+        vand   q10, q10, q4
+       veor    q12, q12, q8
+        veor   q4, q4, q2
+       vand    q8, q8, q15
+        vand   q2, q2, q13
+       vand    q12, q12, q14
+        vand   q4, q4, q9
+       veor    q8, q8, q12
+        veor   q4, q4, q2
+       veor    q12, q12, q11
+        veor   q2, q2, q10
+       veor    q15, q15, q13
+       veor    q14, q14, q9
+       veor    q10, q15, q14
+       vand    q10, q10, q7
+       veor    q7, q7, q1
+       vand    q11, q1, q15
+       vand    q7, q7, q14
+       veor    q1, q11, q10
+       veor    q7, q7, q11
+       veor    q7, q7, q12
+       veor    q4, q4, q12
+       veor    q1, q1, q8
+       veor    q2, q2, q8
+       veor    q7, q7, q0
+       veor    q1, q1, q6
+       veor    q6, q6, q0
+       veor    q4, q4, q7
+       veor    q0, q0, q1
+
+       veor    q1, q1, q5
+       veor    q5, q5, q2
+       veor    q2, q2, q3
+       veor    q3, q3, q5
+       veor    q4, q4, q5
+
+       veor    q6, q6, q3
+       subs    r5,r5,#1
+       bcc     .Lenc_done
+       vext.8  q8, q0, q0, #12 @ x0 <<< 32
+       vext.8  q9, q1, q1, #12
+        veor   q0, q0, q8              @ x0 ^ (x0 <<< 32)
+       vext.8  q10, q4, q4, #12
+        veor   q1, q1, q9
+       vext.8  q11, q6, q6, #12
+        veor   q4, q4, q10
+       vext.8  q12, q3, q3, #12
+        veor   q6, q6, q11
+       vext.8  q13, q7, q7, #12
+        veor   q3, q3, q12
+       vext.8  q14, q2, q2, #12
+        veor   q7, q7, q13
+       vext.8  q15, q5, q5, #12
+        veor   q2, q2, q14
+
+       veor    q9, q9, q0
+        veor   q5, q5, q15
+        vext.8 q0, q0, q0, #8          @ (x0 ^ (x0 <<< 32)) <<< 64)
+       veor    q10, q10, q1
+       veor    q8, q8, q5
+       veor    q9, q9, q5
+        vext.8 q1, q1, q1, #8
+       veor    q13, q13, q3
+        veor   q0, q0, q8
+       veor    q14, q14, q7
+        veor   q1, q1, q9
+        vext.8 q8, q3, q3, #8
+       veor    q12, q12, q6
+        vext.8 q9, q7, q7, #8
+       veor    q15, q15, q2
+        vext.8 q3, q6, q6, #8
+       veor    q11, q11, q4
+        vext.8 q7, q5, q5, #8
+       veor    q12, q12, q5
+        vext.8 q6, q2, q2, #8
+       veor    q11, q11, q5
+        vext.8 q2, q4, q4, #8
+       veor    q5, q9, q13
+       veor    q4, q8, q12
+       veor    q3, q3, q11
+       veor    q7, q7, q15
+       veor    q6, q6, q14
+        @ vmov q4, q8
+       veor    q2, q2, q10
+        @ vmov q5, q9
+       vldmia  r6, {q12}               @ .LSR
+       ite     eq                              @ Thumb2 thing, samity check in ARM
+       addeq   r6,r6,#0x10
+       bne     .Lenc_loop
+       vldmia  r6, {q12}               @ .LSRM0
+       b       .Lenc_loop
+.align 4
+.Lenc_done:
+       vmov.i8 q8,#0x55                        @ compose .LBS0
+       vmov.i8 q9,#0x33                        @ compose .LBS1
+       vshr.u64        q10, q2, #1
+        vshr.u64       q11, q3, #1
+       veor            q10, q10, q5
+        veor           q11, q11, q7
+       vand            q10, q10, q8
+        vand           q11, q11, q8
+       veor            q5, q5, q10
+       vshl.u64        q10, q10, #1
+        veor           q7, q7, q11
+        vshl.u64       q11, q11, #1
+       veor            q2, q2, q10
+        veor           q3, q3, q11
+       vshr.u64        q10, q4, #1
+        vshr.u64       q11, q0, #1
+       veor            q10, q10, q6
+        veor           q11, q11, q1
+       vand            q10, q10, q8
+        vand           q11, q11, q8
+       veor            q6, q6, q10
+       vshl.u64        q10, q10, #1
+        veor           q1, q1, q11
+        vshl.u64       q11, q11, #1
+       veor            q4, q4, q10
+        veor           q0, q0, q11
+       vmov.i8 q8,#0x0f                        @ compose .LBS2
+       vshr.u64        q10, q7, #2
+        vshr.u64       q11, q3, #2
+       veor            q10, q10, q5
+        veor           q11, q11, q2
+       vand            q10, q10, q9
+        vand           q11, q11, q9
+       veor            q5, q5, q10
+       vshl.u64        q10, q10, #2
+        veor           q2, q2, q11
+        vshl.u64       q11, q11, #2
+       veor            q7, q7, q10
+        veor           q3, q3, q11
+       vshr.u64        q10, q1, #2
+        vshr.u64       q11, q0, #2
+       veor            q10, q10, q6
+        veor           q11, q11, q4
+       vand            q10, q10, q9
+        vand           q11, q11, q9
+       veor            q6, q6, q10
+       vshl.u64        q10, q10, #2
+        veor           q4, q4, q11
+        vshl.u64       q11, q11, #2
+       veor            q1, q1, q10
+        veor           q0, q0, q11
+       vshr.u64        q10, q6, #4
+        vshr.u64       q11, q4, #4
+       veor            q10, q10, q5
+        veor           q11, q11, q2
+       vand            q10, q10, q8
+        vand           q11, q11, q8
+       veor            q5, q5, q10
+       vshl.u64        q10, q10, #4
+        veor           q2, q2, q11
+        vshl.u64       q11, q11, #4
+       veor            q6, q6, q10
+        veor           q4, q4, q11
+       vshr.u64        q10, q1, #4
+        vshr.u64       q11, q0, #4
+       veor            q10, q10, q7
+        veor           q11, q11, q3
+       vand            q10, q10, q8
+        vand           q11, q11, q8
+       veor            q7, q7, q10
+       vshl.u64        q10, q10, #4
+        veor           q3, q3, q11
+        vshl.u64       q11, q11, #4
+       veor            q1, q1, q10
+        veor           q0, q0, q11
+       vldmia  r4, {q8}                        @ last round key
+       veor    q4, q4, q8
+       veor    q6, q6, q8
+       veor    q3, q3, q8
+       veor    q7, q7, q8
+       veor    q2, q2, q8
+       veor    q5, q5, q8
+       veor    q0, q0, q8
+       veor    q1, q1, q8
+       bx      lr
+.size  _bsaes_encrypt8,.-_bsaes_encrypt8
+.type  _bsaes_key_convert,%function
+.align 4
+_bsaes_key_convert:
+       adr     r6,_bsaes_key_convert
+       vld1.8  {q7},  [r4]!            @ load round 0 key
+       sub     r6,r6,#_bsaes_key_convert-.LM0
+       vld1.8  {q15}, [r4]!            @ load round 1 key
+
+       vmov.i8 q8,  #0x01                      @ bit masks
+       vmov.i8 q9,  #0x02
+       vmov.i8 q10, #0x04
+       vmov.i8 q11, #0x08
+       vmov.i8 q12, #0x10
+       vmov.i8 q13, #0x20
+       vldmia  r6, {q14}               @ .LM0
+
+#ifdef __ARMEL__
+       vrev32.8        q7,  q7
+       vrev32.8        q15, q15
+#endif
+       sub     r5,r5,#1
+       vstmia  r12!, {q7}              @ save round 0 key
+       b       .Lkey_loop
+
+.align 4
+.Lkey_loop:
+       vtbl.8  d14,{q15},d28
+       vtbl.8  d15,{q15},d29
+       vmov.i8 q6,  #0x40
+       vmov.i8 q15, #0x80
+
+       vtst.8  q0, q7, q8
+       vtst.8  q1, q7, q9
+       vtst.8  q2, q7, q10
+       vtst.8  q3, q7, q11
+       vtst.8  q4, q7, q12
+       vtst.8  q5, q7, q13
+       vtst.8  q6, q7, q6
+       vtst.8  q7, q7, q15
+       vld1.8  {q15}, [r4]!            @ load next round key
+       vmvn    q0, q0          @ "pnot"
+       vmvn    q1, q1
+       vmvn    q5, q5
+       vmvn    q6, q6
+#ifdef __ARMEL__
+       vrev32.8        q15, q15
+#endif
+       subs    r5,r5,#1
+       vstmia  r12!,{q0-q7}            @ write bit-sliced round key
+       bne     .Lkey_loop
+
+       vmov.i8 q7,#0x63                        @ compose .L63
+       @ don't save last round key
+       bx      lr
+.size  _bsaes_key_convert,.-_bsaes_key_convert
+.extern AES_cbc_encrypt
+.extern AES_decrypt
+
+.global        bsaes_cbc_encrypt
+.type  bsaes_cbc_encrypt,%function
+.align 5
+bsaes_cbc_encrypt:
+#ifndef        __KERNEL__
+       cmp     r2, #128
+#ifndef        __thumb__
+       blo     AES_cbc_encrypt
+#else
+       bhs     1f
+       b       AES_cbc_encrypt
+1:
+#endif
+#endif
+
+       @ it is up to the caller to make sure we are called with enc == 0
+
+       mov     ip, sp
+       stmdb   sp!, {r4-r10, lr}
+       VFP_ABI_PUSH
+       ldr     r8, [ip]                        @ IV is 1st arg on the stack
+       mov     r2, r2, lsr#4           @ len in 16 byte blocks
+       sub     sp, #0x10                       @ scratch space to carry over the IV
+       mov     r9, sp                          @ save sp
+
+       ldr     r10, [r3, #240]         @ get # of rounds
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       @ allocate the key schedule on the stack
+       sub     r12, sp, r10, lsl#7             @ 128 bytes per inner round key
+       add     r12, #96                        @ sifze of bit-slices key schedule
+
+       @ populate the key schedule
+       mov     r4, r3                  @ pass key
+       mov     r5, r10                 @ pass # of rounds
+       mov     sp, r12                         @ sp is sp
+       bl      _bsaes_key_convert
+       vldmia  sp, {q6}
+       vstmia  r12,  {q15}             @ save last round key
+       veor    q7, q7, q6      @ fix up round 0 key
+       vstmia  sp, {q7}
+#else
+       ldr     r12, [r3, #244]
+       eors    r12, #1
+       beq     0f
+
+       @ populate the key schedule
+       str     r12, [r3, #244]
+       mov     r4, r3                  @ pass key
+       mov     r5, r10                 @ pass # of rounds
+       add     r12, r3, #248                   @ pass key schedule
+       bl      _bsaes_key_convert
+       add     r4, r3, #248
+       vldmia  r4, {q6}
+       vstmia  r12, {q15}                      @ save last round key
+       veor    q7, q7, q6      @ fix up round 0 key
+       vstmia  r4, {q7}
+
+.align 2
+0:
+#endif
+
+       vld1.8  {q15}, [r8]             @ load IV
+       b       .Lcbc_dec_loop
+
+.align 4
+.Lcbc_dec_loop:
+       subs    r2, r2, #0x8
+       bmi     .Lcbc_dec_loop_finish
+
+       vld1.8  {q0-q1}, [r0]!  @ load input
+       vld1.8  {q2-q3}, [r0]!
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       mov     r4, sp                  @ pass the key
+#else
+       add     r4, r3, #248
+#endif
+       vld1.8  {q4-q5}, [r0]!
+       mov     r5, r10
+       vld1.8  {q6-q7}, [r0]
+       sub     r0, r0, #0x60
+       vstmia  r9, {q15}                       @ put aside IV
+
+       bl      _bsaes_decrypt8
+
+       vldmia  r9, {q14}                       @ reload IV
+       vld1.8  {q8-q9}, [r0]!  @ reload input
+       veor    q0, q0, q14     @ ^= IV
+       vld1.8  {q10-q11}, [r0]!
+       veor    q1, q1, q8
+       veor    q6, q6, q9
+       vld1.8  {q12-q13}, [r0]!
+       veor    q4, q4, q10
+       veor    q2, q2, q11
+       vld1.8  {q14-q15}, [r0]!
+       veor    q7, q7, q12
+       vst1.8  {q0-q1}, [r1]!  @ write output
+       veor    q3, q3, q13
+       vst1.8  {q6}, [r1]!
+       veor    q5, q5, q14
+       vst1.8  {q4}, [r1]!
+       vst1.8  {q2}, [r1]!
+       vst1.8  {q7}, [r1]!
+       vst1.8  {q3}, [r1]!
+       vst1.8  {q5}, [r1]!
+
+       b       .Lcbc_dec_loop
+
+.Lcbc_dec_loop_finish:
+       adds    r2, r2, #8
+       beq     .Lcbc_dec_done
+
+       vld1.8  {q0}, [r0]!             @ load input
+       cmp     r2, #2
+       blo     .Lcbc_dec_one
+       vld1.8  {q1}, [r0]!
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       mov     r4, sp                  @ pass the key
+#else
+       add     r4, r3, #248
+#endif
+       mov     r5, r10
+       vstmia  r9, {q15}                       @ put aside IV
+       beq     .Lcbc_dec_two
+       vld1.8  {q2}, [r0]!
+       cmp     r2, #4
+       blo     .Lcbc_dec_three
+       vld1.8  {q3}, [r0]!
+       beq     .Lcbc_dec_four
+       vld1.8  {q4}, [r0]!
+       cmp     r2, #6
+       blo     .Lcbc_dec_five
+       vld1.8  {q5}, [r0]!
+       beq     .Lcbc_dec_six
+       vld1.8  {q6}, [r0]!
+       sub     r0, r0, #0x70
+
+       bl      _bsaes_decrypt8
+
+       vldmia  r9, {q14}                       @ reload IV
+       vld1.8  {q8-q9}, [r0]!  @ reload input
+       veor    q0, q0, q14     @ ^= IV
+       vld1.8  {q10-q11}, [r0]!
+       veor    q1, q1, q8
+       veor    q6, q6, q9
+       vld1.8  {q12-q13}, [r0]!
+       veor    q4, q4, q10
+       veor    q2, q2, q11
+       vld1.8  {q15}, [r0]!
+       veor    q7, q7, q12
+       vst1.8  {q0-q1}, [r1]!  @ write output
+       veor    q3, q3, q13
+       vst1.8  {q6}, [r1]!
+       vst1.8  {q4}, [r1]!
+       vst1.8  {q2}, [r1]!
+       vst1.8  {q7}, [r1]!
+       vst1.8  {q3}, [r1]!
+       b       .Lcbc_dec_done
+.align 4
+.Lcbc_dec_six:
+       sub     r0, r0, #0x60
+       bl      _bsaes_decrypt8
+       vldmia  r9,{q14}                        @ reload IV
+       vld1.8  {q8-q9}, [r0]!  @ reload input
+       veor    q0, q0, q14     @ ^= IV
+       vld1.8  {q10-q11}, [r0]!
+       veor    q1, q1, q8
+       veor    q6, q6, q9
+       vld1.8  {q12}, [r0]!
+       veor    q4, q4, q10
+       veor    q2, q2, q11
+       vld1.8  {q15}, [r0]!
+       veor    q7, q7, q12
+       vst1.8  {q0-q1}, [r1]!  @ write output
+       vst1.8  {q6}, [r1]!
+       vst1.8  {q4}, [r1]!
+       vst1.8  {q2}, [r1]!
+       vst1.8  {q7}, [r1]!
+       b       .Lcbc_dec_done
+.align 4
+.Lcbc_dec_five:
+       sub     r0, r0, #0x50
+       bl      _bsaes_decrypt8
+       vldmia  r9, {q14}                       @ reload IV
+       vld1.8  {q8-q9}, [r0]!  @ reload input
+       veor    q0, q0, q14     @ ^= IV
+       vld1.8  {q10-q11}, [r0]!
+       veor    q1, q1, q8
+       veor    q6, q6, q9
+       vld1.8  {q15}, [r0]!
+       veor    q4, q4, q10
+       vst1.8  {q0-q1}, [r1]!  @ write output
+       veor    q2, q2, q11
+       vst1.8  {q6}, [r1]!
+       vst1.8  {q4}, [r1]!
+       vst1.8  {q2}, [r1]!
+       b       .Lcbc_dec_done
+.align 4
+.Lcbc_dec_four:
+       sub     r0, r0, #0x40
+       bl      _bsaes_decrypt8
+       vldmia  r9, {q14}                       @ reload IV
+       vld1.8  {q8-q9}, [r0]!  @ reload input
+       veor    q0, q0, q14     @ ^= IV
+       vld1.8  {q10}, [r0]!
+       veor    q1, q1, q8
+       veor    q6, q6, q9
+       vld1.8  {q15}, [r0]!
+       veor    q4, q4, q10
+       vst1.8  {q0-q1}, [r1]!  @ write output
+       vst1.8  {q6}, [r1]!
+       vst1.8  {q4}, [r1]!
+       b       .Lcbc_dec_done
+.align 4
+.Lcbc_dec_three:
+       sub     r0, r0, #0x30
+       bl      _bsaes_decrypt8
+       vldmia  r9, {q14}                       @ reload IV
+       vld1.8  {q8-q9}, [r0]!  @ reload input
+       veor    q0, q0, q14     @ ^= IV
+       vld1.8  {q15}, [r0]!
+       veor    q1, q1, q8
+       veor    q6, q6, q9
+       vst1.8  {q0-q1}, [r1]!  @ write output
+       vst1.8  {q6}, [r1]!
+       b       .Lcbc_dec_done
+.align 4
+.Lcbc_dec_two:
+       sub     r0, r0, #0x20
+       bl      _bsaes_decrypt8
+       vldmia  r9, {q14}                       @ reload IV
+       vld1.8  {q8}, [r0]!             @ reload input
+       veor    q0, q0, q14     @ ^= IV
+       vld1.8  {q15}, [r0]!            @ reload input
+       veor    q1, q1, q8
+       vst1.8  {q0-q1}, [r1]!  @ write output
+       b       .Lcbc_dec_done
+.align 4
+.Lcbc_dec_one:
+       sub     r0, r0, #0x10
+       mov     r10, r1                 @ save original out pointer
+       mov     r1, r9                  @ use the iv scratch space as out buffer
+       mov     r2, r3
+       vmov    q4,q15          @ just in case ensure that IV
+       vmov    q5,q0                   @ and input are preserved
+       bl      AES_decrypt
+       vld1.8  {q0}, [r9,:64]          @ load result
+       veor    q0, q0, q4      @ ^= IV
+       vmov    q15, q5         @ q5 holds input
+       vst1.8  {q0}, [r10]             @ write output
+
+.Lcbc_dec_done:
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       vmov.i32        q0, #0
+       vmov.i32        q1, #0
+.Lcbc_dec_bzero:                               @ wipe key schedule [if any]
+       vstmia          sp!, {q0-q1}
+       cmp             sp, r9
+       bne             .Lcbc_dec_bzero
+#endif
+
+       mov     sp, r9
+       add     sp, #0x10                       @ add sp,r9,#0x10 is no good for thumb
+       vst1.8  {q15}, [r8]             @ return IV
+       VFP_ABI_POP
+       ldmia   sp!, {r4-r10, pc}
+.size  bsaes_cbc_encrypt,.-bsaes_cbc_encrypt
+.extern        AES_encrypt
+.global        bsaes_ctr32_encrypt_blocks
+.type  bsaes_ctr32_encrypt_blocks,%function
+.align 5
+bsaes_ctr32_encrypt_blocks:
+       cmp     r2, #8                  @ use plain AES for
+       blo     .Lctr_enc_short                 @ small sizes
+
+       mov     ip, sp
+       stmdb   sp!, {r4-r10, lr}
+       VFP_ABI_PUSH
+       ldr     r8, [ip]                        @ ctr is 1st arg on the stack
+       sub     sp, sp, #0x10                   @ scratch space to carry over the ctr
+       mov     r9, sp                          @ save sp
+
+       ldr     r10, [r3, #240]         @ get # of rounds
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       @ allocate the key schedule on the stack
+       sub     r12, sp, r10, lsl#7             @ 128 bytes per inner round key
+       add     r12, #96                        @ size of bit-sliced key schedule
+
+       @ populate the key schedule
+       mov     r4, r3                  @ pass key
+       mov     r5, r10                 @ pass # of rounds
+       mov     sp, r12                         @ sp is sp
+       bl      _bsaes_key_convert
+       veor    q7,q7,q15       @ fix up last round key
+       vstmia  r12, {q7}                       @ save last round key
+
+       vld1.8  {q0}, [r8]              @ load counter
+       add     r8, r6, #.LREVM0SR-.LM0 @ borrow r8
+       vldmia  sp, {q4}                @ load round0 key
+#else
+       ldr     r12, [r3, #244]
+       eors    r12, #1
+       beq     0f
+
+       @ populate the key schedule
+       str     r12, [r3, #244]
+       mov     r4, r3                  @ pass key
+       mov     r5, r10                 @ pass # of rounds
+       add     r12, r3, #248                   @ pass key schedule
+       bl      _bsaes_key_convert
+       veor    q7,q7,q15       @ fix up last round key
+       vstmia  r12, {q7}                       @ save last round key
+
+.align 2
+0:     add     r12, r3, #248
+       vld1.8  {q0}, [r8]              @ load counter
+       adrl    r8, .LREVM0SR                   @ borrow r8
+       vldmia  r12, {q4}                       @ load round0 key
+       sub     sp, #0x10                       @ place for adjusted round0 key
+#endif
+
+       vmov.i32        q8,#1           @ compose 1<<96
+       veor            q9,q9,q9
+       vrev32.8        q0,q0
+       vext.8          q8,q9,q8,#4
+       vrev32.8        q4,q4
+       vadd.u32        q9,q8,q8        @ compose 2<<96
+       vstmia  sp, {q4}                @ save adjusted round0 key
+       b       .Lctr_enc_loop
+
+.align 4
+.Lctr_enc_loop:
+       vadd.u32        q10, q8, q9     @ compose 3<<96
+       vadd.u32        q1, q0, q8      @ +1
+       vadd.u32        q2, q0, q9      @ +2
+       vadd.u32        q3, q0, q10     @ +3
+       vadd.u32        q4, q1, q10
+       vadd.u32        q5, q2, q10
+       vadd.u32        q6, q3, q10
+       vadd.u32        q7, q4, q10
+       vadd.u32        q10, q5, q10    @ next counter
+
+       @ Borrow prologue from _bsaes_encrypt8 to use the opportunity
+       @ to flip byte order in 32-bit counter
+
+       vldmia          sp, {q9}                @ load round0 key
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x10           @ pass next round key
+#else
+       add             r4, r3, #264
+#endif
+       vldmia          r8, {q8}                        @ .LREVM0SR
+       mov             r5, r10                 @ pass rounds
+       vstmia          r9, {q10}                       @ save next counter
+       sub             r6, r8, #.LREVM0SR-.LSR @ pass constants
+
+       bl              _bsaes_encrypt8_alt
+
+       subs            r2, r2, #8
+       blo             .Lctr_enc_loop_done
+
+       vld1.8          {q8-q9}, [r0]!  @ load input
+       vld1.8          {q10-q11}, [r0]!
+       veor            q0, q8
+       veor            q1, q9
+       vld1.8          {q12-q13}, [r0]!
+       veor            q4, q10
+       veor            q6, q11
+       vld1.8          {q14-q15}, [r0]!
+       veor            q3, q12
+       vst1.8          {q0-q1}, [r1]!  @ write output
+       veor            q7, q13
+       veor            q2, q14
+       vst1.8          {q4}, [r1]!
+       veor            q5, q15
+       vst1.8          {q6}, [r1]!
+       vmov.i32        q8, #1                  @ compose 1<<96
+       vst1.8          {q3}, [r1]!
+       veor            q9, q9, q9
+       vst1.8          {q7}, [r1]!
+       vext.8          q8, q9, q8, #4
+       vst1.8          {q2}, [r1]!
+       vadd.u32        q9,q8,q8                @ compose 2<<96
+       vst1.8          {q5}, [r1]!
+       vldmia          r9, {q0}                        @ load counter
+
+       bne             .Lctr_enc_loop
+       b               .Lctr_enc_done
+
+.align 4
+.Lctr_enc_loop_done:
+       add             r2, r2, #8
+       vld1.8          {q8}, [r0]!     @ load input
+       veor            q0, q8
+       vst1.8          {q0}, [r1]!     @ write output
+       cmp             r2, #2
+       blo             .Lctr_enc_done
+       vld1.8          {q9}, [r0]!
+       veor            q1, q9
+       vst1.8          {q1}, [r1]!
+       beq             .Lctr_enc_done
+       vld1.8          {q10}, [r0]!
+       veor            q4, q10
+       vst1.8          {q4}, [r1]!
+       cmp             r2, #4
+       blo             .Lctr_enc_done
+       vld1.8          {q11}, [r0]!
+       veor            q6, q11
+       vst1.8          {q6}, [r1]!
+       beq             .Lctr_enc_done
+       vld1.8          {q12}, [r0]!
+       veor            q3, q12
+       vst1.8          {q3}, [r1]!
+       cmp             r2, #6
+       blo             .Lctr_enc_done
+       vld1.8          {q13}, [r0]!
+       veor            q7, q13
+       vst1.8          {q7}, [r1]!
+       beq             .Lctr_enc_done
+       vld1.8          {q14}, [r0]
+       veor            q2, q14
+       vst1.8          {q2}, [r1]!
+
+.Lctr_enc_done:
+       vmov.i32        q0, #0
+       vmov.i32        q1, #0
+#ifndef        BSAES_ASM_EXTENDED_KEY
+.Lctr_enc_bzero:                       @ wipe key schedule [if any]
+       vstmia          sp!, {q0-q1}
+       cmp             sp, r9
+       bne             .Lctr_enc_bzero
+#else
+       vstmia          sp, {q0-q1}
+#endif
+
+       mov     sp, r9
+       add     sp, #0x10               @ add sp,r9,#0x10 is no good for thumb
+       VFP_ABI_POP
+       ldmia   sp!, {r4-r10, pc}       @ return
+
+.align 4
+.Lctr_enc_short:
+       ldr     ip, [sp]                @ ctr pointer is passed on stack
+       stmdb   sp!, {r4-r8, lr}
+
+       mov     r4, r0          @ copy arguments
+       mov     r5, r1
+       mov     r6, r2
+       mov     r7, r3
+       ldr     r8, [ip, #12]           @ load counter LSW
+       vld1.8  {q1}, [ip]              @ load whole counter value
+#ifdef __ARMEL__
+       rev     r8, r8
+#endif
+       sub     sp, sp, #0x10
+       vst1.8  {q1}, [sp,:64]  @ copy counter value
+       sub     sp, sp, #0x10
+
+.Lctr_enc_short_loop:
+       add     r0, sp, #0x10           @ input counter value
+       mov     r1, sp                  @ output on the stack
+       mov     r2, r7                  @ key
+
+       bl      AES_encrypt
+
+       vld1.8  {q0}, [r4]!     @ load input
+       vld1.8  {q1}, [sp,:64]  @ load encrypted counter
+       add     r8, r8, #1
+#ifdef __ARMEL__
+       rev     r0, r8
+       str     r0, [sp, #0x1c]         @ next counter value
+#else
+       str     r8, [sp, #0x1c]         @ next counter value
+#endif
+       veor    q0,q0,q1
+       vst1.8  {q0}, [r5]!     @ store output
+       subs    r6, r6, #1
+       bne     .Lctr_enc_short_loop
+
+       vmov.i32        q0, #0
+       vmov.i32        q1, #0
+       vstmia          sp!, {q0-q1}
+
+       ldmia   sp!, {r4-r8, pc}
+.size  bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
+.globl bsaes_xts_encrypt
+.type  bsaes_xts_encrypt,%function
+.align 4
+bsaes_xts_encrypt:
+       mov     ip, sp
+       stmdb   sp!, {r4-r10, lr}               @ 0x20
+       VFP_ABI_PUSH
+       mov     r6, sp                          @ future r3
+
+       mov     r7, r0
+       mov     r8, r1
+       mov     r9, r2
+       mov     r10, r3
+
+       sub     r0, sp, #0x10                   @ 0x10
+       bic     r0, #0xf                        @ align at 16 bytes
+       mov     sp, r0
+
+#ifdef XTS_CHAIN_TWEAK
+       ldr     r0, [ip]                        @ pointer to input tweak
+#else
+       @ generate initial tweak
+       ldr     r0, [ip, #4]                    @ iv[]
+       mov     r1, sp
+       ldr     r2, [ip, #0]                    @ key2
+       bl      AES_encrypt
+       mov     r0,sp                           @ pointer to initial tweak
+#endif
+
+       ldr     r1, [r10, #240]         @ get # of rounds
+       mov     r3, r6
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       @ allocate the key schedule on the stack
+       sub     r12, sp, r1, lsl#7              @ 128 bytes per inner round key
+       @ add   r12, #96                        @ size of bit-sliced key schedule
+       sub     r12, #48                        @ place for tweak[9]
+
+       @ populate the key schedule
+       mov     r4, r10                 @ pass key
+       mov     r5, r1                  @ pass # of rounds
+       mov     sp, r12
+       add     r12, #0x90                      @ pass key schedule
+       bl      _bsaes_key_convert
+       veor    q7, q7, q15     @ fix up last round key
+       vstmia  r12, {q7}                       @ save last round key
+#else
+       ldr     r12, [r10, #244]
+       eors    r12, #1
+       beq     0f
+
+       str     r12, [r10, #244]
+       mov     r4, r10                 @ pass key
+       mov     r5, r1                  @ pass # of rounds
+       add     r12, r10, #248                  @ pass key schedule
+       bl      _bsaes_key_convert
+       veor    q7, q7, q15     @ fix up last round key
+       vstmia  r12, {q7}
+
+.align 2
+0:     sub     sp, #0x90                       @ place for tweak[9]
+#endif
+
+       vld1.8  {q8}, [r0]                      @ initial tweak
+       adr     r2, .Lxts_magic
+
+       subs    r9, #0x80
+       blo     .Lxts_enc_short
+       b       .Lxts_enc_loop
+
+.align 4
+.Lxts_enc_loop:
+       vldmia          r2, {q5}        @ load XTS magic
+       vshr.s64        q6, q8, #63
+       mov             r0, sp
+       vand            q6, q6, q5
+       vadd.u64        q9, q8, q8
+       vst1.64         {q8}, [r0,:128]!
+       vswp            d13,d12
+       vshr.s64        q7, q9, #63
+       veor            q9, q9, q6
+       vand            q7, q7, q5
+       vadd.u64        q10, q9, q9
+       vst1.64         {q9}, [r0,:128]!
+       vswp            d15,d14
+       vshr.s64        q6, q10, #63
+       veor            q10, q10, q7
+       vand            q6, q6, q5
+       vld1.8          {q0}, [r7]!
+       vadd.u64        q11, q10, q10
+       vst1.64         {q10}, [r0,:128]!
+       vswp            d13,d12
+       vshr.s64        q7, q11, #63
+       veor            q11, q11, q6
+       vand            q7, q7, q5
+       vld1.8          {q1}, [r7]!
+       veor            q0, q0, q8
+       vadd.u64        q12, q11, q11
+       vst1.64         {q11}, [r0,:128]!
+       vswp            d15,d14
+       vshr.s64        q6, q12, #63
+       veor            q12, q12, q7
+       vand            q6, q6, q5
+       vld1.8          {q2}, [r7]!
+       veor            q1, q1, q9
+       vadd.u64        q13, q12, q12
+       vst1.64         {q12}, [r0,:128]!
+       vswp            d13,d12
+       vshr.s64        q7, q13, #63
+       veor            q13, q13, q6
+       vand            q7, q7, q5
+       vld1.8          {q3}, [r7]!
+       veor            q2, q2, q10
+       vadd.u64        q14, q13, q13
+       vst1.64         {q13}, [r0,:128]!
+       vswp            d15,d14
+       vshr.s64        q6, q14, #63
+       veor            q14, q14, q7
+       vand            q6, q6, q5
+       vld1.8          {q4}, [r7]!
+       veor            q3, q3, q11
+       vadd.u64        q15, q14, q14
+       vst1.64         {q14}, [r0,:128]!
+       vswp            d13,d12
+       vshr.s64        q7, q15, #63
+       veor            q15, q15, q6
+       vand            q7, q7, q5
+       vld1.8          {q5}, [r7]!
+       veor            q4, q4, q12
+       vadd.u64        q8, q15, q15
+       vst1.64         {q15}, [r0,:128]!
+       vswp            d15,d14
+       veor            q8, q8, q7
+       vst1.64         {q8}, [r0,:128]         @ next round tweak
+
+       vld1.8          {q6-q7}, [r7]!
+       veor            q5, q5, q13
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, r10, #248                   @ pass key schedule
+#endif
+       veor            q6, q6, q14
+       mov             r5, r1                  @ pass rounds
+       veor            q7, q7, q15
+       mov             r0, sp
+
+       bl              _bsaes_encrypt8
+
+       vld1.64         {q8-q9}, [r0,:128]!
+       vld1.64         {q10-q11}, [r0,:128]!
+       veor            q0, q0, q8
+       vld1.64         {q12-q13}, [r0,:128]!
+       veor            q1, q1, q9
+       veor            q8, q4, q10
+       vst1.8          {q0-q1}, [r8]!
+       veor            q9, q6, q11
+       vld1.64         {q14-q15}, [r0,:128]!
+       veor            q10, q3, q12
+       vst1.8          {q8-q9}, [r8]!
+       veor            q11, q7, q13
+       veor            q12, q2, q14
+       vst1.8          {q10-q11}, [r8]!
+       veor            q13, q5, q15
+       vst1.8          {q12-q13}, [r8]!
+
+       vld1.64         {q8}, [r0,:128]         @ next round tweak
+
+       subs            r9, #0x80
+       bpl             .Lxts_enc_loop
+
+.Lxts_enc_short:
+       adds            r9, #0x70
+       bmi             .Lxts_enc_done
+
+       vldmia          r2, {q5}        @ load XTS magic
+       vshr.s64        q7, q8, #63
+       mov             r0, sp
+       vand            q7, q7, q5
+       vadd.u64        q9, q8, q8
+       vst1.64         {q8}, [r0,:128]!
+       vswp            d15,d14
+       vshr.s64        q6, q9, #63
+       veor            q9, q9, q7
+       vand            q6, q6, q5
+       vadd.u64        q10, q9, q9
+       vst1.64         {q9}, [r0,:128]!
+       vswp            d13,d12
+       vshr.s64        q7, q10, #63
+       veor            q10, q10, q6
+       vand            q7, q7, q5
+       vld1.8          {q0}, [r7]!
+       subs            r9, #0x10
+       bmi             .Lxts_enc_1
+       vadd.u64        q11, q10, q10
+       vst1.64         {q10}, [r0,:128]!
+       vswp            d15,d14
+       vshr.s64        q6, q11, #63
+       veor            q11, q11, q7
+       vand            q6, q6, q5
+       vld1.8          {q1}, [r7]!
+       subs            r9, #0x10
+       bmi             .Lxts_enc_2
+       veor            q0, q0, q8
+       vadd.u64        q12, q11, q11
+       vst1.64         {q11}, [r0,:128]!
+       vswp            d13,d12
+       vshr.s64        q7, q12, #63
+       veor            q12, q12, q6
+       vand            q7, q7, q5
+       vld1.8          {q2}, [r7]!
+       subs            r9, #0x10
+       bmi             .Lxts_enc_3
+       veor            q1, q1, q9
+       vadd.u64        q13, q12, q12
+       vst1.64         {q12}, [r0,:128]!
+       vswp            d15,d14
+       vshr.s64        q6, q13, #63
+       veor            q13, q13, q7
+       vand            q6, q6, q5
+       vld1.8          {q3}, [r7]!
+       subs            r9, #0x10
+       bmi             .Lxts_enc_4
+       veor            q2, q2, q10
+       vadd.u64        q14, q13, q13
+       vst1.64         {q13}, [r0,:128]!
+       vswp            d13,d12
+       vshr.s64        q7, q14, #63
+       veor            q14, q14, q6
+       vand            q7, q7, q5
+       vld1.8          {q4}, [r7]!
+       subs            r9, #0x10
+       bmi             .Lxts_enc_5
+       veor            q3, q3, q11
+       vadd.u64        q15, q14, q14
+       vst1.64         {q14}, [r0,:128]!
+       vswp            d15,d14
+       vshr.s64        q6, q15, #63
+       veor            q15, q15, q7
+       vand            q6, q6, q5
+       vld1.8          {q5}, [r7]!
+       subs            r9, #0x10
+       bmi             .Lxts_enc_6
+       veor            q4, q4, q12
+       sub             r9, #0x10
+       vst1.64         {q15}, [r0,:128]                @ next round tweak
+
+       vld1.8          {q6}, [r7]!
+       veor            q5, q5, q13
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, r10, #248                   @ pass key schedule
+#endif
+       veor            q6, q6, q14
+       mov             r5, r1                  @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_encrypt8
+
+       vld1.64         {q8-q9}, [r0,:128]!
+       vld1.64         {q10-q11}, [r0,:128]!
+       veor            q0, q0, q8
+       vld1.64         {q12-q13}, [r0,:128]!
+       veor            q1, q1, q9
+       veor            q8, q4, q10
+       vst1.8          {q0-q1}, [r8]!
+       veor            q9, q6, q11
+       vld1.64         {q14}, [r0,:128]!
+       veor            q10, q3, q12
+       vst1.8          {q8-q9}, [r8]!
+       veor            q11, q7, q13
+       veor            q12, q2, q14
+       vst1.8          {q10-q11}, [r8]!
+       vst1.8          {q12}, [r8]!
+
+       vld1.64         {q8}, [r0,:128]         @ next round tweak
+       b               .Lxts_enc_done
+.align 4
+.Lxts_enc_6:
+       vst1.64         {q14}, [r0,:128]                @ next round tweak
+
+       veor            q4, q4, q12
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, r10, #248                   @ pass key schedule
+#endif
+       veor            q5, q5, q13
+       mov             r5, r1                  @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_encrypt8
+
+       vld1.64         {q8-q9}, [r0,:128]!
+       vld1.64         {q10-q11}, [r0,:128]!
+       veor            q0, q0, q8
+       vld1.64         {q12-q13}, [r0,:128]!
+       veor            q1, q1, q9
+       veor            q8, q4, q10
+       vst1.8          {q0-q1}, [r8]!
+       veor            q9, q6, q11
+       veor            q10, q3, q12
+       vst1.8          {q8-q9}, [r8]!
+       veor            q11, q7, q13
+       vst1.8          {q10-q11}, [r8]!
+
+       vld1.64         {q8}, [r0,:128]         @ next round tweak
+       b               .Lxts_enc_done
+
+@ put this in range for both ARM and Thumb mode adr instructions
+.align 5
+.Lxts_magic:
+       .quad   1, 0x87
+
+.align 5
+.Lxts_enc_5:
+       vst1.64         {q13}, [r0,:128]                @ next round tweak
+
+       veor            q3, q3, q11
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, r10, #248                   @ pass key schedule
+#endif
+       veor            q4, q4, q12
+       mov             r5, r1                  @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_encrypt8
+
+       vld1.64         {q8-q9}, [r0,:128]!
+       vld1.64         {q10-q11}, [r0,:128]!
+       veor            q0, q0, q8
+       vld1.64         {q12}, [r0,:128]!
+       veor            q1, q1, q9
+       veor            q8, q4, q10
+       vst1.8          {q0-q1}, [r8]!
+       veor            q9, q6, q11
+       veor            q10, q3, q12
+       vst1.8          {q8-q9}, [r8]!
+       vst1.8          {q10}, [r8]!
+
+       vld1.64         {q8}, [r0,:128]         @ next round tweak
+       b               .Lxts_enc_done
+.align 4
+.Lxts_enc_4:
+       vst1.64         {q12}, [r0,:128]                @ next round tweak
+
+       veor            q2, q2, q10
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, r10, #248                   @ pass key schedule
+#endif
+       veor            q3, q3, q11
+       mov             r5, r1                  @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_encrypt8
+
+       vld1.64         {q8-q9}, [r0,:128]!
+       vld1.64         {q10-q11}, [r0,:128]!
+       veor            q0, q0, q8
+       veor            q1, q1, q9
+       veor            q8, q4, q10
+       vst1.8          {q0-q1}, [r8]!
+       veor            q9, q6, q11
+       vst1.8          {q8-q9}, [r8]!
+
+       vld1.64         {q8}, [r0,:128]         @ next round tweak
+       b               .Lxts_enc_done
+.align 4
+.Lxts_enc_3:
+       vst1.64         {q11}, [r0,:128]                @ next round tweak
+
+       veor            q1, q1, q9
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, r10, #248                   @ pass key schedule
+#endif
+       veor            q2, q2, q10
+       mov             r5, r1                  @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_encrypt8
+
+       vld1.64         {q8-q9}, [r0,:128]!
+       vld1.64         {q10}, [r0,:128]!
+       veor            q0, q0, q8
+       veor            q1, q1, q9
+       veor            q8, q4, q10
+       vst1.8          {q0-q1}, [r8]!
+       vst1.8          {q8}, [r8]!
+
+       vld1.64         {q8}, [r0,:128]         @ next round tweak
+       b               .Lxts_enc_done
+.align 4
+.Lxts_enc_2:
+       vst1.64         {q10}, [r0,:128]                @ next round tweak
+
+       veor            q0, q0, q8
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, r10, #248                   @ pass key schedule
+#endif
+       veor            q1, q1, q9
+       mov             r5, r1                  @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_encrypt8
+
+       vld1.64         {q8-q9}, [r0,:128]!
+       veor            q0, q0, q8
+       veor            q1, q1, q9
+       vst1.8          {q0-q1}, [r8]!
+
+       vld1.64         {q8}, [r0,:128]         @ next round tweak
+       b               .Lxts_enc_done
+.align 4
+.Lxts_enc_1:
+       mov             r0, sp
+       veor            q0, q8
+       mov             r1, sp
+       vst1.8          {q0}, [sp,:128]
+       mov             r2, r10
+       mov             r4, r3                          @ preserve fp
+
+       bl              AES_encrypt
+
+       vld1.8          {q0}, [sp,:128]
+       veor            q0, q0, q8
+       vst1.8          {q0}, [r8]!
+       mov             r3, r4
+
+       vmov            q8, q9          @ next round tweak
+
+.Lxts_enc_done:
+#ifndef        XTS_CHAIN_TWEAK
+       adds            r9, #0x10
+       beq             .Lxts_enc_ret
+       sub             r6, r8, #0x10
+
+.Lxts_enc_steal:
+       ldrb            r0, [r7], #1
+       ldrb            r1, [r8, #-0x10]
+       strb            r0, [r8, #-0x10]
+       strb            r1, [r8], #1
+
+       subs            r9, #1
+       bhi             .Lxts_enc_steal
+
+       vld1.8          {q0}, [r6]
+       mov             r0, sp
+       veor            q0, q0, q8
+       mov             r1, sp
+       vst1.8          {q0}, [sp,:128]
+       mov             r2, r10
+       mov             r4, r3                  @ preserve fp
+
+       bl              AES_encrypt
+
+       vld1.8          {q0}, [sp,:128]
+       veor            q0, q0, q8
+       vst1.8          {q0}, [r6]
+       mov             r3, r4
+#endif
+
+.Lxts_enc_ret:
+       bic             r0, r3, #0xf
+       vmov.i32        q0, #0
+       vmov.i32        q1, #0
+#ifdef XTS_CHAIN_TWEAK
+       ldr             r1, [r3, #0x20+VFP_ABI_FRAME]   @ chain tweak
+#endif
+.Lxts_enc_bzero:                               @ wipe key schedule [if any]
+       vstmia          sp!, {q0-q1}
+       cmp             sp, r0
+       bne             .Lxts_enc_bzero
+
+       mov             sp, r3
+#ifdef XTS_CHAIN_TWEAK
+       vst1.8          {q8}, [r1]
+#endif
+       VFP_ABI_POP
+       ldmia           sp!, {r4-r10, pc}       @ return
+
+.size  bsaes_xts_encrypt,.-bsaes_xts_encrypt
+
+.globl bsaes_xts_decrypt
+.type  bsaes_xts_decrypt,%function
+.align 4
+bsaes_xts_decrypt:
+       mov     ip, sp
+       stmdb   sp!, {r4-r10, lr}               @ 0x20
+       VFP_ABI_PUSH
+       mov     r6, sp                          @ future r3
+
+       mov     r7, r0
+       mov     r8, r1
+       mov     r9, r2
+       mov     r10, r3
+
+       sub     r0, sp, #0x10                   @ 0x10
+       bic     r0, #0xf                        @ align at 16 bytes
+       mov     sp, r0
+
+#ifdef XTS_CHAIN_TWEAK
+       ldr     r0, [ip]                        @ pointer to input tweak
+#else
+       @ generate initial tweak
+       ldr     r0, [ip, #4]                    @ iv[]
+       mov     r1, sp
+       ldr     r2, [ip, #0]                    @ key2
+       bl      AES_encrypt
+       mov     r0, sp                          @ pointer to initial tweak
+#endif
+
+       ldr     r1, [r10, #240]         @ get # of rounds
+       mov     r3, r6
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       @ allocate the key schedule on the stack
+       sub     r12, sp, r1, lsl#7              @ 128 bytes per inner round key
+       @ add   r12, #96                        @ size of bit-sliced key schedule
+       sub     r12, #48                        @ place for tweak[9]
+
+       @ populate the key schedule
+       mov     r4, r10                 @ pass key
+       mov     r5, r1                  @ pass # of rounds
+       mov     sp, r12
+       add     r12, #0x90                      @ pass key schedule
+       bl      _bsaes_key_convert
+       add     r4, sp, #0x90
+       vldmia  r4, {q6}
+       vstmia  r12,  {q15}             @ save last round key
+       veor    q7, q7, q6      @ fix up round 0 key
+       vstmia  r4, {q7}
+#else
+       ldr     r12, [r10, #244]
+       eors    r12, #1
+       beq     0f
+
+       str     r12, [r10, #244]
+       mov     r4, r10                 @ pass key
+       mov     r5, r1                  @ pass # of rounds
+       add     r12, r10, #248                  @ pass key schedule
+       bl      _bsaes_key_convert
+       add     r4, r10, #248
+       vldmia  r4, {q6}
+       vstmia  r12,  {q15}             @ save last round key
+       veor    q7, q7, q6      @ fix up round 0 key
+       vstmia  r4, {q7}
+
+.align 2
+0:     sub     sp, #0x90                       @ place for tweak[9]
+#endif
+       vld1.8  {q8}, [r0]                      @ initial tweak
+       adr     r2, .Lxts_magic
+
+       tst     r9, #0xf                        @ if not multiple of 16
+       it      ne                              @ Thumb2 thing, sanity check in ARM
+       subne   r9, #0x10                       @ subtract another 16 bytes
+       subs    r9, #0x80
+
+       blo     .Lxts_dec_short
+       b       .Lxts_dec_loop
+
+.align 4
+.Lxts_dec_loop:
+       vldmia          r2, {q5}        @ load XTS magic
+       vshr.s64        q6, q8, #63
+       mov             r0, sp
+       vand            q6, q6, q5
+       vadd.u64        q9, q8, q8
+       vst1.64         {q8}, [r0,:128]!
+       vswp            d13,d12
+       vshr.s64        q7, q9, #63
+       veor            q9, q9, q6
+       vand            q7, q7, q5
+       vadd.u64        q10, q9, q9
+       vst1.64         {q9}, [r0,:128]!
+       vswp            d15,d14
+       vshr.s64        q6, q10, #63
+       veor            q10, q10, q7
+       vand            q6, q6, q5
+       vld1.8          {q0}, [r7]!
+       vadd.u64        q11, q10, q10
+       vst1.64         {q10}, [r0,:128]!
+       vswp            d13,d12
+       vshr.s64        q7, q11, #63
+       veor            q11, q11, q6
+       vand            q7, q7, q5
+       vld1.8          {q1}, [r7]!
+       veor            q0, q0, q8
+       vadd.u64        q12, q11, q11
+       vst1.64         {q11}, [r0,:128]!
+       vswp            d15,d14
+       vshr.s64        q6, q12, #63
+       veor            q12, q12, q7
+       vand            q6, q6, q5
+       vld1.8          {q2}, [r7]!
+       veor            q1, q1, q9
+       vadd.u64        q13, q12, q12
+       vst1.64         {q12}, [r0,:128]!
+       vswp            d13,d12
+       vshr.s64        q7, q13, #63
+       veor            q13, q13, q6
+       vand            q7, q7, q5
+       vld1.8          {q3}, [r7]!
+       veor            q2, q2, q10
+       vadd.u64        q14, q13, q13
+       vst1.64         {q13}, [r0,:128]!
+       vswp            d15,d14
+       vshr.s64        q6, q14, #63
+       veor            q14, q14, q7
+       vand            q6, q6, q5
+       vld1.8          {q4}, [r7]!
+       veor            q3, q3, q11
+       vadd.u64        q15, q14, q14
+       vst1.64         {q14}, [r0,:128]!
+       vswp            d13,d12
+       vshr.s64        q7, q15, #63
+       veor            q15, q15, q6
+       vand            q7, q7, q5
+       vld1.8          {q5}, [r7]!
+       veor            q4, q4, q12
+       vadd.u64        q8, q15, q15
+       vst1.64         {q15}, [r0,:128]!
+       vswp            d15,d14
+       veor            q8, q8, q7
+       vst1.64         {q8}, [r0,:128]         @ next round tweak
+
+       vld1.8          {q6-q7}, [r7]!
+       veor            q5, q5, q13
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, r10, #248                   @ pass key schedule
+#endif
+       veor            q6, q6, q14
+       mov             r5, r1                  @ pass rounds
+       veor            q7, q7, q15
+       mov             r0, sp
+
+       bl              _bsaes_decrypt8
+
+       vld1.64         {q8-q9}, [r0,:128]!
+       vld1.64         {q10-q11}, [r0,:128]!
+       veor            q0, q0, q8
+       vld1.64         {q12-q13}, [r0,:128]!
+       veor            q1, q1, q9
+       veor            q8, q6, q10
+       vst1.8          {q0-q1}, [r8]!
+       veor            q9, q4, q11
+       vld1.64         {q14-q15}, [r0,:128]!
+       veor            q10, q2, q12
+       vst1.8          {q8-q9}, [r8]!
+       veor            q11, q7, q13
+       veor            q12, q3, q14
+       vst1.8          {q10-q11}, [r8]!
+       veor            q13, q5, q15
+       vst1.8          {q12-q13}, [r8]!
+
+       vld1.64         {q8}, [r0,:128]         @ next round tweak
+
+       subs            r9, #0x80
+       bpl             .Lxts_dec_loop
+
+.Lxts_dec_short:
+       adds            r9, #0x70
+       bmi             .Lxts_dec_done
+
+       vldmia          r2, {q5}        @ load XTS magic
+       vshr.s64        q7, q8, #63
+       mov             r0, sp
+       vand            q7, q7, q5
+       vadd.u64        q9, q8, q8
+       vst1.64         {q8}, [r0,:128]!
+       vswp            d15,d14
+       vshr.s64        q6, q9, #63
+       veor            q9, q9, q7
+       vand            q6, q6, q5
+       vadd.u64        q10, q9, q9
+       vst1.64         {q9}, [r0,:128]!
+       vswp            d13,d12
+       vshr.s64        q7, q10, #63
+       veor            q10, q10, q6
+       vand            q7, q7, q5
+       vld1.8          {q0}, [r7]!
+       subs            r9, #0x10
+       bmi             .Lxts_dec_1
+       vadd.u64        q11, q10, q10
+       vst1.64         {q10}, [r0,:128]!
+       vswp            d15,d14
+       vshr.s64        q6, q11, #63
+       veor            q11, q11, q7
+       vand            q6, q6, q5
+       vld1.8          {q1}, [r7]!
+       subs            r9, #0x10
+       bmi             .Lxts_dec_2
+       veor            q0, q0, q8
+       vadd.u64        q12, q11, q11
+       vst1.64         {q11}, [r0,:128]!
+       vswp            d13,d12
+       vshr.s64        q7, q12, #63
+       veor            q12, q12, q6
+       vand            q7, q7, q5
+       vld1.8          {q2}, [r7]!
+       subs            r9, #0x10
+       bmi             .Lxts_dec_3
+       veor            q1, q1, q9
+       vadd.u64        q13, q12, q12
+       vst1.64         {q12}, [r0,:128]!
+       vswp            d15,d14
+       vshr.s64        q6, q13, #63
+       veor            q13, q13, q7
+       vand            q6, q6, q5
+       vld1.8          {q3}, [r7]!
+       subs            r9, #0x10
+       bmi             .Lxts_dec_4
+       veor            q2, q2, q10
+       vadd.u64        q14, q13, q13
+       vst1.64         {q13}, [r0,:128]!
+       vswp            d13,d12
+       vshr.s64        q7, q14, #63
+       veor            q14, q14, q6
+       vand            q7, q7, q5
+       vld1.8          {q4}, [r7]!
+       subs            r9, #0x10
+       bmi             .Lxts_dec_5
+       veor            q3, q3, q11
+       vadd.u64        q15, q14, q14
+       vst1.64         {q14}, [r0,:128]!
+       vswp            d15,d14
+       vshr.s64        q6, q15, #63
+       veor            q15, q15, q7
+       vand            q6, q6, q5
+       vld1.8          {q5}, [r7]!
+       subs            r9, #0x10
+       bmi             .Lxts_dec_6
+       veor            q4, q4, q12
+       sub             r9, #0x10
+       vst1.64         {q15}, [r0,:128]                @ next round tweak
+
+       vld1.8          {q6}, [r7]!
+       veor            q5, q5, q13
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, r10, #248                   @ pass key schedule
+#endif
+       veor            q6, q6, q14
+       mov             r5, r1                  @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_decrypt8
+
+       vld1.64         {q8-q9}, [r0,:128]!
+       vld1.64         {q10-q11}, [r0,:128]!
+       veor            q0, q0, q8
+       vld1.64         {q12-q13}, [r0,:128]!
+       veor            q1, q1, q9
+       veor            q8, q6, q10
+       vst1.8          {q0-q1}, [r8]!
+       veor            q9, q4, q11
+       vld1.64         {q14}, [r0,:128]!
+       veor            q10, q2, q12
+       vst1.8          {q8-q9}, [r8]!
+       veor            q11, q7, q13
+       veor            q12, q3, q14
+       vst1.8          {q10-q11}, [r8]!
+       vst1.8          {q12}, [r8]!
+
+       vld1.64         {q8}, [r0,:128]         @ next round tweak
+       b               .Lxts_dec_done
+.align 4
+.Lxts_dec_6:
+       vst1.64         {q14}, [r0,:128]                @ next round tweak
+
+       veor            q4, q4, q12
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, r10, #248                   @ pass key schedule
+#endif
+       veor            q5, q5, q13
+       mov             r5, r1                  @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_decrypt8
+
+       vld1.64         {q8-q9}, [r0,:128]!
+       vld1.64         {q10-q11}, [r0,:128]!
+       veor            q0, q0, q8
+       vld1.64         {q12-q13}, [r0,:128]!
+       veor            q1, q1, q9
+       veor            q8, q6, q10
+       vst1.8          {q0-q1}, [r8]!
+       veor            q9, q4, q11
+       veor            q10, q2, q12
+       vst1.8          {q8-q9}, [r8]!
+       veor            q11, q7, q13
+       vst1.8          {q10-q11}, [r8]!
+
+       vld1.64         {q8}, [r0,:128]         @ next round tweak
+       b               .Lxts_dec_done
+.align 4
+.Lxts_dec_5:
+       vst1.64         {q13}, [r0,:128]                @ next round tweak
+
+       veor            q3, q3, q11
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, r10, #248                   @ pass key schedule
+#endif
+       veor            q4, q4, q12
+       mov             r5, r1                  @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_decrypt8
+
+       vld1.64         {q8-q9}, [r0,:128]!
+       vld1.64         {q10-q11}, [r0,:128]!
+       veor            q0, q0, q8
+       vld1.64         {q12}, [r0,:128]!
+       veor            q1, q1, q9
+       veor            q8, q6, q10
+       vst1.8          {q0-q1}, [r8]!
+       veor            q9, q4, q11
+       veor            q10, q2, q12
+       vst1.8          {q8-q9}, [r8]!
+       vst1.8          {q10}, [r8]!
+
+       vld1.64         {q8}, [r0,:128]         @ next round tweak
+       b               .Lxts_dec_done
+.align 4
+.Lxts_dec_4:
+       vst1.64         {q12}, [r0,:128]                @ next round tweak
+
+       veor            q2, q2, q10
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, r10, #248                   @ pass key schedule
+#endif
+       veor            q3, q3, q11
+       mov             r5, r1                  @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_decrypt8
+
+       vld1.64         {q8-q9}, [r0,:128]!
+       vld1.64         {q10-q11}, [r0,:128]!
+       veor            q0, q0, q8
+       veor            q1, q1, q9
+       veor            q8, q6, q10
+       vst1.8          {q0-q1}, [r8]!
+       veor            q9, q4, q11
+       vst1.8          {q8-q9}, [r8]!
+
+       vld1.64         {q8}, [r0,:128]         @ next round tweak
+       b               .Lxts_dec_done
+.align 4
+.Lxts_dec_3:
+       vst1.64         {q11}, [r0,:128]                @ next round tweak
+
+       veor            q1, q1, q9
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, r10, #248                   @ pass key schedule
+#endif
+       veor            q2, q2, q10
+       mov             r5, r1                  @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_decrypt8
+
+       vld1.64         {q8-q9}, [r0,:128]!
+       vld1.64         {q10}, [r0,:128]!
+       veor            q0, q0, q8
+       veor            q1, q1, q9
+       veor            q8, q6, q10
+       vst1.8          {q0-q1}, [r8]!
+       vst1.8          {q8}, [r8]!
+
+       vld1.64         {q8}, [r0,:128]         @ next round tweak
+       b               .Lxts_dec_done
+.align 4
+.Lxts_dec_2:
+       vst1.64         {q10}, [r0,:128]                @ next round tweak
+
+       veor            q0, q0, q8
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, r10, #248                   @ pass key schedule
+#endif
+       veor            q1, q1, q9
+       mov             r5, r1                  @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_decrypt8
+
+       vld1.64         {q8-q9}, [r0,:128]!
+       veor            q0, q0, q8
+       veor            q1, q1, q9
+       vst1.8          {q0-q1}, [r8]!
+
+       vld1.64         {q8}, [r0,:128]         @ next round tweak
+       b               .Lxts_dec_done
+.align 4
+.Lxts_dec_1:
+       mov             r0, sp
+       veor            q0, q8
+       mov             r1, sp
+       vst1.8          {q0}, [sp,:128]
+       mov             r2, r10
+       mov             r4, r3                          @ preserve fp
+       mov             r5, r2                  @ preserve magic
+
+       bl              AES_decrypt
+
+       vld1.8          {q0}, [sp,:128]
+       veor            q0, q0, q8
+       vst1.8          {q0}, [r8]!
+       mov             r3, r4
+       mov             r2, r5
+
+       vmov            q8, q9          @ next round tweak
+
+.Lxts_dec_done:
+#ifndef        XTS_CHAIN_TWEAK
+       adds            r9, #0x10
+       beq             .Lxts_dec_ret
+
+       @ calculate one round of extra tweak for the stolen ciphertext
+       vldmia          r2, {q5}
+       vshr.s64        q6, q8, #63
+       vand            q6, q6, q5
+       vadd.u64        q9, q8, q8
+       vswp            d13,d12
+       veor            q9, q9, q6
+
+       @ perform the final decryption with the last tweak value
+       vld1.8          {q0}, [r7]!
+       mov             r0, sp
+       veor            q0, q0, q9
+       mov             r1, sp
+       vst1.8          {q0}, [sp,:128]
+       mov             r2, r10
+       mov             r4, r3                  @ preserve fp
+
+       bl              AES_decrypt
+
+       vld1.8          {q0}, [sp,:128]
+       veor            q0, q0, q9
+       vst1.8          {q0}, [r8]
+
+       mov             r6, r8
+.Lxts_dec_steal:
+       ldrb            r1, [r8]
+       ldrb            r0, [r7], #1
+       strb            r1, [r8, #0x10]
+       strb            r0, [r8], #1
+
+       subs            r9, #1
+       bhi             .Lxts_dec_steal
+
+       vld1.8          {q0}, [r6]
+       mov             r0, sp
+       veor            q0, q8
+       mov             r1, sp
+       vst1.8          {q0}, [sp,:128]
+       mov             r2, r10
+
+       bl              AES_decrypt
+
+       vld1.8          {q0}, [sp,:128]
+       veor            q0, q0, q8
+       vst1.8          {q0}, [r6]
+       mov             r3, r4
+#endif
+
+.Lxts_dec_ret:
+       bic             r0, r3, #0xf
+       vmov.i32        q0, #0
+       vmov.i32        q1, #0
+#ifdef XTS_CHAIN_TWEAK
+       ldr             r1, [r3, #0x20+VFP_ABI_FRAME]   @ chain tweak
+#endif
+.Lxts_dec_bzero:                               @ wipe key schedule [if any]
+       vstmia          sp!, {q0-q1}
+       cmp             sp, r0
+       bne             .Lxts_dec_bzero
+
+       mov             sp, r3
+#ifdef XTS_CHAIN_TWEAK
+       vst1.8          {q8}, [r1]
+#endif
+       VFP_ABI_POP
+       ldmia           sp!, {r4-r10, pc}       @ return
+
+.size  bsaes_xts_decrypt,.-bsaes_xts_decrypt
+#endif
diff --git a/arch/arm/crypto/aesbs-glue.c b/arch/arm/crypto/aesbs-glue.c
new file mode 100644 (file)
index 0000000..4522366
--- /dev/null
@@ -0,0 +1,434 @@
+/*
+ * linux/arch/arm/crypto/aesbs-glue.c - glue code for NEON bit sliced AES
+ *
+ * Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <asm/neon.h>
+#include <crypto/aes.h>
+#include <crypto/ablk_helper.h>
+#include <crypto/algapi.h>
+#include <linux/module.h>
+
+#include "aes_glue.h"
+
+#define BIT_SLICED_KEY_MAXSIZE (128 * (AES_MAXNR - 1) + 2 * AES_BLOCK_SIZE)
+
+struct BS_KEY {
+       struct AES_KEY  rk;
+       int             converted;
+       u8 __aligned(8) bs[BIT_SLICED_KEY_MAXSIZE];
+} __aligned(8);
+
+asmlinkage void bsaes_enc_key_convert(u8 out[], struct AES_KEY const *in);
+asmlinkage void bsaes_dec_key_convert(u8 out[], struct AES_KEY const *in);
+
+asmlinkage void bsaes_cbc_encrypt(u8 const in[], u8 out[], u32 bytes,
+                                 struct BS_KEY *key, u8 iv[]);
+
+asmlinkage void bsaes_ctr32_encrypt_blocks(u8 const in[], u8 out[], u32 blocks,
+                                          struct BS_KEY *key, u8 const iv[]);
+
+asmlinkage void bsaes_xts_encrypt(u8 const in[], u8 out[], u32 bytes,
+                                 struct BS_KEY *key, u8 tweak[]);
+
+asmlinkage void bsaes_xts_decrypt(u8 const in[], u8 out[], u32 bytes,
+                                 struct BS_KEY *key, u8 tweak[]);
+
+struct aesbs_cbc_ctx {
+       struct AES_KEY  enc;
+       struct BS_KEY   dec;
+};
+
+struct aesbs_ctr_ctx {
+       struct BS_KEY   enc;
+};
+
+struct aesbs_xts_ctx {
+       struct BS_KEY   enc;
+       struct BS_KEY   dec;
+       struct AES_KEY  twkey;
+};
+
+static int aesbs_cbc_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+                            unsigned int key_len)
+{
+       struct aesbs_cbc_ctx *ctx = crypto_tfm_ctx(tfm);
+       int bits = key_len * 8;
+
+       if (private_AES_set_encrypt_key(in_key, bits, &ctx->enc)) {
+               tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+               return -EINVAL;
+       }
+       ctx->dec.rk = ctx->enc;
+       private_AES_set_decrypt_key(in_key, bits, &ctx->dec.rk);
+       ctx->dec.converted = 0;
+       return 0;
+}
+
+static int aesbs_ctr_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+                            unsigned int key_len)
+{
+       struct aesbs_ctr_ctx *ctx = crypto_tfm_ctx(tfm);
+       int bits = key_len * 8;
+
+       if (private_AES_set_encrypt_key(in_key, bits, &ctx->enc.rk)) {
+               tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+               return -EINVAL;
+       }
+       ctx->enc.converted = 0;
+       return 0;
+}
+
+static int aesbs_xts_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+                            unsigned int key_len)
+{
+       struct aesbs_xts_ctx *ctx = crypto_tfm_ctx(tfm);
+       int bits = key_len * 4;
+
+       if (private_AES_set_encrypt_key(in_key, bits, &ctx->enc.rk)) {
+               tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+               return -EINVAL;
+       }
+       ctx->dec.rk = ctx->enc.rk;
+       private_AES_set_decrypt_key(in_key, bits, &ctx->dec.rk);
+       private_AES_set_encrypt_key(in_key + key_len / 2, bits, &ctx->twkey);
+       ctx->enc.converted = ctx->dec.converted = 0;
+       return 0;
+}
+
+static int aesbs_cbc_encrypt(struct blkcipher_desc *desc,
+                            struct scatterlist *dst,
+                            struct scatterlist *src, unsigned int nbytes)
+{
+       struct aesbs_cbc_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+       struct blkcipher_walk walk;
+       int err;
+
+       blkcipher_walk_init(&walk, dst, src, nbytes);
+       err = blkcipher_walk_virt(desc, &walk);
+
+       while (walk.nbytes) {
+               u32 blocks = walk.nbytes / AES_BLOCK_SIZE;
+               u8 *src = walk.src.virt.addr;
+
+               if (walk.dst.virt.addr == walk.src.virt.addr) {
+                       u8 *iv = walk.iv;
+
+                       do {
+                               crypto_xor(src, iv, AES_BLOCK_SIZE);
+                               AES_encrypt(src, src, &ctx->enc);
+                               iv = src;
+                               src += AES_BLOCK_SIZE;
+                       } while (--blocks);
+                       memcpy(walk.iv, iv, AES_BLOCK_SIZE);
+               } else {
+                       u8 *dst = walk.dst.virt.addr;
+
+                       do {
+                               crypto_xor(walk.iv, src, AES_BLOCK_SIZE);
+                               AES_encrypt(walk.iv, dst, &ctx->enc);
+                               memcpy(walk.iv, dst, AES_BLOCK_SIZE);
+                               src += AES_BLOCK_SIZE;
+                               dst += AES_BLOCK_SIZE;
+                       } while (--blocks);
+               }
+               err = blkcipher_walk_done(desc, &walk, 0);
+       }
+       return err;
+}
+
+static int aesbs_cbc_decrypt(struct blkcipher_desc *desc,
+                            struct scatterlist *dst,
+                            struct scatterlist *src, unsigned int nbytes)
+{
+       struct aesbs_cbc_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+       struct blkcipher_walk walk;
+       int err;
+
+       blkcipher_walk_init(&walk, dst, src, nbytes);
+       err = blkcipher_walk_virt_block(desc, &walk, 8 * AES_BLOCK_SIZE);
+
+       while ((walk.nbytes / AES_BLOCK_SIZE) >= 8) {
+               kernel_neon_begin();
+               bsaes_cbc_encrypt(walk.src.virt.addr, walk.dst.virt.addr,
+                                 walk.nbytes, &ctx->dec, walk.iv);
+               kernel_neon_end();
+               err = blkcipher_walk_done(desc, &walk, 0);
+       }
+       while (walk.nbytes) {
+               u32 blocks = walk.nbytes / AES_BLOCK_SIZE;
+               u8 *dst = walk.dst.virt.addr;
+               u8 *src = walk.src.virt.addr;
+               u8 bk[2][AES_BLOCK_SIZE];
+               u8 *iv = walk.iv;
+
+               do {
+                       if (walk.dst.virt.addr == walk.src.virt.addr)
+                               memcpy(bk[blocks & 1], src, AES_BLOCK_SIZE);
+
+                       AES_decrypt(src, dst, &ctx->dec.rk);
+                       crypto_xor(dst, iv, AES_BLOCK_SIZE);
+
+                       if (walk.dst.virt.addr == walk.src.virt.addr)
+                               iv = bk[blocks & 1];
+                       else
+                               iv = src;
+
+                       dst += AES_BLOCK_SIZE;
+                       src += AES_BLOCK_SIZE;
+               } while (--blocks);
+               err = blkcipher_walk_done(desc, &walk, 0);
+       }
+       return err;
+}
+
+static void inc_be128_ctr(__be32 ctr[], u32 addend)
+{
+       int i;
+
+       for (i = 3; i >= 0; i--, addend = 1) {
+               u32 n = be32_to_cpu(ctr[i]) + addend;
+
+               ctr[i] = cpu_to_be32(n);
+               if (n >= addend)
+                       break;
+       }
+}
+
+static int aesbs_ctr_encrypt(struct blkcipher_desc *desc,
+                            struct scatterlist *dst, struct scatterlist *src,
+                            unsigned int nbytes)
+{
+       struct aesbs_ctr_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+       struct blkcipher_walk walk;
+       u32 blocks;
+       int err;
+
+       blkcipher_walk_init(&walk, dst, src, nbytes);
+       err = blkcipher_walk_virt_block(desc, &walk, 8 * AES_BLOCK_SIZE);
+
+       while ((blocks = walk.nbytes / AES_BLOCK_SIZE)) {
+               u32 tail = walk.nbytes % AES_BLOCK_SIZE;
+               __be32 *ctr = (__be32 *)walk.iv;
+               u32 headroom = UINT_MAX - be32_to_cpu(ctr[3]);
+
+               /* avoid 32 bit counter overflow in the NEON code */
+               if (unlikely(headroom < blocks)) {
+                       blocks = headroom + 1;
+                       tail = walk.nbytes - blocks * AES_BLOCK_SIZE;
+               }
+               kernel_neon_begin();
+               bsaes_ctr32_encrypt_blocks(walk.src.virt.addr,
+                                          walk.dst.virt.addr, blocks,
+                                          &ctx->enc, walk.iv);
+               kernel_neon_end();
+               inc_be128_ctr(ctr, blocks);
+
+               nbytes -= blocks * AES_BLOCK_SIZE;
+               if (nbytes && nbytes == tail && nbytes <= AES_BLOCK_SIZE)
+                       break;
+
+               err = blkcipher_walk_done(desc, &walk, tail);
+       }
+       if (walk.nbytes) {
+               u8 *tdst = walk.dst.virt.addr + blocks * AES_BLOCK_SIZE;
+               u8 *tsrc = walk.src.virt.addr + blocks * AES_BLOCK_SIZE;
+               u8 ks[AES_BLOCK_SIZE];
+
+               AES_encrypt(walk.iv, ks, &ctx->enc.rk);
+               if (tdst != tsrc)
+                       memcpy(tdst, tsrc, nbytes);
+               crypto_xor(tdst, ks, nbytes);
+               err = blkcipher_walk_done(desc, &walk, 0);
+       }
+       return err;
+}
+
+static int aesbs_xts_encrypt(struct blkcipher_desc *desc,
+                            struct scatterlist *dst,
+                            struct scatterlist *src, unsigned int nbytes)
+{
+       struct aesbs_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+       struct blkcipher_walk walk;
+       int err;
+
+       blkcipher_walk_init(&walk, dst, src, nbytes);
+       err = blkcipher_walk_virt_block(desc, &walk, 8 * AES_BLOCK_SIZE);
+
+       /* generate the initial tweak */
+       AES_encrypt(walk.iv, walk.iv, &ctx->twkey);
+
+       while (walk.nbytes) {
+               kernel_neon_begin();
+               bsaes_xts_encrypt(walk.src.virt.addr, walk.dst.virt.addr,
+                                 walk.nbytes, &ctx->enc, walk.iv);
+               kernel_neon_end();
+               err = blkcipher_walk_done(desc, &walk, 0);
+       }
+       return err;
+}
+
+static int aesbs_xts_decrypt(struct blkcipher_desc *desc,
+                            struct scatterlist *dst,
+                            struct scatterlist *src, unsigned int nbytes)
+{
+       struct aesbs_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+       struct blkcipher_walk walk;
+       int err;
+
+       blkcipher_walk_init(&walk, dst, src, nbytes);
+       err = blkcipher_walk_virt_block(desc, &walk, 8 * AES_BLOCK_SIZE);
+
+       /* generate the initial tweak */
+       AES_encrypt(walk.iv, walk.iv, &ctx->twkey);
+
+       while (walk.nbytes) {
+               kernel_neon_begin();
+               bsaes_xts_decrypt(walk.src.virt.addr, walk.dst.virt.addr,
+                                 walk.nbytes, &ctx->dec, walk.iv);
+               kernel_neon_end();
+               err = blkcipher_walk_done(desc, &walk, 0);
+       }
+       return err;
+}
+
+static struct crypto_alg aesbs_algs[] = { {
+       .cra_name               = "__cbc-aes-neonbs",
+       .cra_driver_name        = "__driver-cbc-aes-neonbs",
+       .cra_priority           = 0,
+       .cra_flags              = CRYPTO_ALG_TYPE_BLKCIPHER,
+       .cra_blocksize          = AES_BLOCK_SIZE,
+       .cra_ctxsize            = sizeof(struct aesbs_cbc_ctx),
+       .cra_alignmask          = 7,
+       .cra_type               = &crypto_blkcipher_type,
+       .cra_module             = THIS_MODULE,
+       .cra_blkcipher = {
+               .min_keysize    = AES_MIN_KEY_SIZE,
+               .max_keysize    = AES_MAX_KEY_SIZE,
+               .ivsize         = AES_BLOCK_SIZE,
+               .setkey         = aesbs_cbc_set_key,
+               .encrypt        = aesbs_cbc_encrypt,
+               .decrypt        = aesbs_cbc_decrypt,
+       },
+}, {
+       .cra_name               = "__ctr-aes-neonbs",
+       .cra_driver_name        = "__driver-ctr-aes-neonbs",
+       .cra_priority           = 0,
+       .cra_flags              = CRYPTO_ALG_TYPE_BLKCIPHER,
+       .cra_blocksize          = 1,
+       .cra_ctxsize            = sizeof(struct aesbs_ctr_ctx),
+       .cra_alignmask          = 7,
+       .cra_type               = &crypto_blkcipher_type,
+       .cra_module             = THIS_MODULE,
+       .cra_blkcipher = {
+               .min_keysize    = AES_MIN_KEY_SIZE,
+               .max_keysize    = AES_MAX_KEY_SIZE,
+               .ivsize         = AES_BLOCK_SIZE,
+               .setkey         = aesbs_ctr_set_key,
+               .encrypt        = aesbs_ctr_encrypt,
+               .decrypt        = aesbs_ctr_encrypt,
+       },
+}, {
+       .cra_name               = "__xts-aes-neonbs",
+       .cra_driver_name        = "__driver-xts-aes-neonbs",
+       .cra_priority           = 0,
+       .cra_flags              = CRYPTO_ALG_TYPE_BLKCIPHER,
+       .cra_blocksize          = AES_BLOCK_SIZE,
+       .cra_ctxsize            = sizeof(struct aesbs_xts_ctx),
+       .cra_alignmask          = 7,
+       .cra_type               = &crypto_blkcipher_type,
+       .cra_module             = THIS_MODULE,
+       .cra_blkcipher = {
+               .min_keysize    = 2 * AES_MIN_KEY_SIZE,
+               .max_keysize    = 2 * AES_MAX_KEY_SIZE,
+               .ivsize         = AES_BLOCK_SIZE,
+               .setkey         = aesbs_xts_set_key,
+               .encrypt        = aesbs_xts_encrypt,
+               .decrypt        = aesbs_xts_decrypt,
+       },
+}, {
+       .cra_name               = "cbc(aes)",
+       .cra_driver_name        = "cbc-aes-neonbs",
+       .cra_priority           = 300,
+       .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
+       .cra_blocksize          = AES_BLOCK_SIZE,
+       .cra_ctxsize            = sizeof(struct async_helper_ctx),
+       .cra_alignmask          = 7,
+       .cra_type               = &crypto_ablkcipher_type,
+       .cra_module             = THIS_MODULE,
+       .cra_init               = ablk_init,
+       .cra_exit               = ablk_exit,
+       .cra_ablkcipher = {
+               .min_keysize    = AES_MIN_KEY_SIZE,
+               .max_keysize    = AES_MAX_KEY_SIZE,
+               .ivsize         = AES_BLOCK_SIZE,
+               .setkey         = ablk_set_key,
+               .encrypt        = __ablk_encrypt,
+               .decrypt        = ablk_decrypt,
+       }
+}, {
+       .cra_name               = "ctr(aes)",
+       .cra_driver_name        = "ctr-aes-neonbs",
+       .cra_priority           = 300,
+       .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
+       .cra_blocksize          = 1,
+       .cra_ctxsize            = sizeof(struct async_helper_ctx),
+       .cra_alignmask          = 7,
+       .cra_type               = &crypto_ablkcipher_type,
+       .cra_module             = THIS_MODULE,
+       .cra_init               = ablk_init,
+       .cra_exit               = ablk_exit,
+       .cra_ablkcipher = {
+               .min_keysize    = AES_MIN_KEY_SIZE,
+               .max_keysize    = AES_MAX_KEY_SIZE,
+               .ivsize         = AES_BLOCK_SIZE,
+               .setkey         = ablk_set_key,
+               .encrypt        = ablk_encrypt,
+               .decrypt        = ablk_decrypt,
+       }
+}, {
+       .cra_name               = "xts(aes)",
+       .cra_driver_name        = "xts-aes-neonbs",
+       .cra_priority           = 300,
+       .cra_flags              = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
+       .cra_blocksize          = AES_BLOCK_SIZE,
+       .cra_ctxsize            = sizeof(struct async_helper_ctx),
+       .cra_alignmask          = 7,
+       .cra_type               = &crypto_ablkcipher_type,
+       .cra_module             = THIS_MODULE,
+       .cra_init               = ablk_init,
+       .cra_exit               = ablk_exit,
+       .cra_ablkcipher = {
+               .min_keysize    = 2 * AES_MIN_KEY_SIZE,
+               .max_keysize    = 2 * AES_MAX_KEY_SIZE,
+               .ivsize         = AES_BLOCK_SIZE,
+               .setkey         = ablk_set_key,
+               .encrypt        = ablk_encrypt,
+               .decrypt        = ablk_decrypt,
+       }
+} };
+
+static int __init aesbs_mod_init(void)
+{
+       if (!cpu_has_neon())
+               return -ENODEV;
+
+       return crypto_register_algs(aesbs_algs, ARRAY_SIZE(aesbs_algs));
+}
+
+static void __exit aesbs_mod_exit(void)
+{
+       crypto_unregister_algs(aesbs_algs, ARRAY_SIZE(aesbs_algs));
+}
+
+module_init(aesbs_mod_init);
+module_exit(aesbs_mod_exit);
+
+MODULE_DESCRIPTION("Bit sliced AES in CBC/CTR/XTS modes using NEON");
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/crypto/bsaes-armv7.pl b/arch/arm/crypto/bsaes-armv7.pl
new file mode 100644 (file)
index 0000000..f3d96d9
--- /dev/null
@@ -0,0 +1,2467 @@
+#!/usr/bin/env perl
+
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+#
+# Specific modes and adaptation for Linux kernel by Ard Biesheuvel
+# <ard.biesheuvel@linaro.org>. Permission to use under GPL terms is
+# granted.
+# ====================================================================
+
+# Bit-sliced AES for ARM NEON
+#
+# February 2012.
+#
+# This implementation is direct adaptation of bsaes-x86_64 module for
+# ARM NEON. Except that this module is endian-neutral [in sense that
+# it can be compiled for either endianness] by courtesy of vld1.8's
+# neutrality. Initial version doesn't implement interface to OpenSSL,
+# only low-level primitives and unsupported entry points, just enough
+# to collect performance results, which for Cortex-A8 core are:
+#
+# encrypt      19.5 cycles per byte processed with 128-bit key
+# decrypt      22.1 cycles per byte processed with 128-bit key
+# key conv.    440  cycles per 128-bit key/0.18 of 8x block
+#
+# Snapdragon S4 encrypts byte in 17.6 cycles and decrypts in 19.7,
+# which is [much] worse than anticipated (for further details see
+# http://www.openssl.org/~appro/Snapdragon-S4.html).
+#
+# Cortex-A15 manages in 14.2/16.1 cycles [when integer-only code
+# manages in 20.0 cycles].
+#
+# When comparing to x86_64 results keep in mind that NEON unit is
+# [mostly] single-issue and thus can't [fully] benefit from
+# instruction-level parallelism. And when comparing to aes-armv4
+# results keep in mind key schedule conversion overhead (see
+# bsaes-x86_64.pl for further details)...
+#
+#                                              <appro@openssl.org>
+
+# April-August 2013
+#
+# Add CBC, CTR and XTS subroutines, adapt for kernel use.
+#
+#                                      <ard.biesheuvel@linaro.org>
+
+while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
+open STDOUT,">$output";
+
+my ($inp,$out,$len,$key)=("r0","r1","r2","r3");
+my @XMM=map("q$_",(0..15));
+
+{
+my ($key,$rounds,$const)=("r4","r5","r6");
+
+sub Dlo()   { shift=~m|q([1]?[0-9])|?"d".($1*2):"";     }
+sub Dhi()   { shift=~m|q([1]?[0-9])|?"d".($1*2+1):"";   }
+
+sub Sbox {
+# input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
+# output in lsb > [b0, b1, b4, b6, b3, b7, b2, b5] < msb
+my @b=@_[0..7];
+my @t=@_[8..11];
+my @s=@_[12..15];
+       &InBasisChange  (@b);
+       &Inv_GF256      (@b[6,5,0,3,7,1,4,2],@t,@s);
+       &OutBasisChange (@b[7,1,4,2,6,5,0,3]);
+}
+
+sub InBasisChange {
+# input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
+# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb 
+my @b=@_[0..7];
+$code.=<<___;
+       veor    @b[2], @b[2], @b[1]
+       veor    @b[5], @b[5], @b[6]
+       veor    @b[3], @b[3], @b[0]
+       veor    @b[6], @b[6], @b[2]
+       veor    @b[5], @b[5], @b[0]
+
+       veor    @b[6], @b[6], @b[3]
+       veor    @b[3], @b[3], @b[7]
+       veor    @b[7], @b[7], @b[5]
+       veor    @b[3], @b[3], @b[4]
+       veor    @b[4], @b[4], @b[5]
+
+       veor    @b[2], @b[2], @b[7]
+       veor    @b[3], @b[3], @b[1]
+       veor    @b[1], @b[1], @b[5]
+___
+}
+
+sub OutBasisChange {
+# input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
+# output in lsb > [b6, b1, b2, b4, b7, b0, b3, b5] < msb
+my @b=@_[0..7];
+$code.=<<___;
+       veor    @b[0], @b[0], @b[6]
+       veor    @b[1], @b[1], @b[4]
+       veor    @b[4], @b[4], @b[6]
+       veor    @b[2], @b[2], @b[0]
+       veor    @b[6], @b[6], @b[1]
+
+       veor    @b[1], @b[1], @b[5]
+       veor    @b[5], @b[5], @b[3]
+       veor    @b[3], @b[3], @b[7]
+       veor    @b[7], @b[7], @b[5]
+       veor    @b[2], @b[2], @b[5]
+
+       veor    @b[4], @b[4], @b[7]
+___
+}
+
+sub InvSbox {
+# input in lsb         > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
+# output in lsb        > [b0, b1, b6, b4, b2, b7, b3, b5] < msb
+my @b=@_[0..7];
+my @t=@_[8..11];
+my @s=@_[12..15];
+       &InvInBasisChange       (@b);
+       &Inv_GF256              (@b[5,1,2,6,3,7,0,4],@t,@s);
+       &InvOutBasisChange      (@b[3,7,0,4,5,1,2,6]);
+}
+
+sub InvInBasisChange {         # OutBasisChange in reverse (with twist)
+my @b=@_[5,1,2,6,3,7,0,4];
+$code.=<<___
+        veor   @b[1], @b[1], @b[7]
+       veor    @b[4], @b[4], @b[7]
+
+       veor    @b[7], @b[7], @b[5]
+        veor   @b[1], @b[1], @b[3]
+       veor    @b[2], @b[2], @b[5]
+       veor    @b[3], @b[3], @b[7]
+
+       veor    @b[6], @b[6], @b[1]
+       veor    @b[2], @b[2], @b[0]
+        veor   @b[5], @b[5], @b[3]
+       veor    @b[4], @b[4], @b[6]
+       veor    @b[0], @b[0], @b[6]
+       veor    @b[1], @b[1], @b[4]
+___
+}
+
+sub InvOutBasisChange {                # InBasisChange in reverse
+my @b=@_[2,5,7,3,6,1,0,4];
+$code.=<<___;
+       veor    @b[1], @b[1], @b[5]
+       veor    @b[2], @b[2], @b[7]
+
+       veor    @b[3], @b[3], @b[1]
+       veor    @b[4], @b[4], @b[5]
+       veor    @b[7], @b[7], @b[5]
+       veor    @b[3], @b[3], @b[4]
+        veor   @b[5], @b[5], @b[0]
+       veor    @b[3], @b[3], @b[7]
+        veor   @b[6], @b[6], @b[2]
+        veor   @b[2], @b[2], @b[1]
+       veor    @b[6], @b[6], @b[3]
+
+       veor    @b[3], @b[3], @b[0]
+       veor    @b[5], @b[5], @b[6]
+___
+}
+
+sub Mul_GF4 {
+#;*************************************************************
+#;* Mul_GF4: Input x0-x1,y0-y1 Output x0-x1 Temp t0 (8) *
+#;*************************************************************
+my ($x0,$x1,$y0,$y1,$t0,$t1)=@_;
+$code.=<<___;
+       veor    $t0, $y0, $y1
+       vand    $t0, $t0, $x0
+       veor    $x0, $x0, $x1
+       vand    $t1, $x1, $y0
+       vand    $x0, $x0, $y1
+       veor    $x1, $t1, $t0
+       veor    $x0, $x0, $t1
+___
+}
+
+sub Mul_GF4_N {                                # not used, see next subroutine
+# multiply and scale by N
+my ($x0,$x1,$y0,$y1,$t0)=@_;
+$code.=<<___;
+       veor    $t0, $y0, $y1
+       vand    $t0, $t0, $x0
+       veor    $x0, $x0, $x1
+       vand    $x1, $x1, $y0
+       vand    $x0, $x0, $y1
+       veor    $x1, $x1, $x0
+       veor    $x0, $x0, $t0
+___
+}
+
+sub Mul_GF4_N_GF4 {
+# interleaved Mul_GF4_N and Mul_GF4
+my ($x0,$x1,$y0,$y1,$t0,
+    $x2,$x3,$y2,$y3,$t1)=@_;
+$code.=<<___;
+       veor    $t0, $y0, $y1
+        veor   $t1, $y2, $y3
+       vand    $t0, $t0, $x0
+        vand   $t1, $t1, $x2
+       veor    $x0, $x0, $x1
+        veor   $x2, $x2, $x3
+       vand    $x1, $x1, $y0
+        vand   $x3, $x3, $y2
+       vand    $x0, $x0, $y1
+        vand   $x2, $x2, $y3
+       veor    $x1, $x1, $x0
+        veor   $x2, $x2, $x3
+       veor    $x0, $x0, $t0
+        veor   $x3, $x3, $t1
+___
+}
+sub Mul_GF16_2 {
+my @x=@_[0..7];
+my @y=@_[8..11];
+my @t=@_[12..15];
+$code.=<<___;
+       veor    @t[0], @x[0], @x[2]
+       veor    @t[1], @x[1], @x[3]
+___
+       &Mul_GF4        (@x[0], @x[1], @y[0], @y[1], @t[2..3]);
+$code.=<<___;
+       veor    @y[0], @y[0], @y[2]
+       veor    @y[1], @y[1], @y[3]
+___
+       Mul_GF4_N_GF4   (@t[0], @t[1], @y[0], @y[1], @t[3],
+                        @x[2], @x[3], @y[2], @y[3], @t[2]);
+$code.=<<___;
+       veor    @x[0], @x[0], @t[0]
+       veor    @x[2], @x[2], @t[0]
+       veor    @x[1], @x[1], @t[1]
+       veor    @x[3], @x[3], @t[1]
+
+       veor    @t[0], @x[4], @x[6]
+       veor    @t[1], @x[5], @x[7]
+___
+       &Mul_GF4_N_GF4  (@t[0], @t[1], @y[0], @y[1], @t[3],
+                        @x[6], @x[7], @y[2], @y[3], @t[2]);
+$code.=<<___;
+       veor    @y[0], @y[0], @y[2]
+       veor    @y[1], @y[1], @y[3]
+___
+       &Mul_GF4        (@x[4], @x[5], @y[0], @y[1], @t[2..3]);
+$code.=<<___;
+       veor    @x[4], @x[4], @t[0]
+       veor    @x[6], @x[6], @t[0]
+       veor    @x[5], @x[5], @t[1]
+       veor    @x[7], @x[7], @t[1]
+___
+}
+sub Inv_GF256 {
+#;********************************************************************
+#;* Inv_GF256: Input x0-x7 Output x0-x7 Temp t0-t3,s0-s3 (144)       *
+#;********************************************************************
+my @x=@_[0..7];
+my @t=@_[8..11];
+my @s=@_[12..15];
+# direct optimizations from hardware
+$code.=<<___;
+       veor    @t[3], @x[4], @x[6]
+       veor    @t[2], @x[5], @x[7]
+       veor    @t[1], @x[1], @x[3]
+       veor    @s[1], @x[7], @x[6]
+        vmov   @t[0], @t[2]
+       veor    @s[0], @x[0], @x[2]
+
+       vorr    @t[2], @t[2], @t[1]
+       veor    @s[3], @t[3], @t[0]
+       vand    @s[2], @t[3], @s[0]
+       vorr    @t[3], @t[3], @s[0]
+       veor    @s[0], @s[0], @t[1]
+       vand    @t[0], @t[0], @t[1]
+       veor    @t[1], @x[3], @x[2]
+       vand    @s[3], @s[3], @s[0]
+       vand    @s[1], @s[1], @t[1]
+       veor    @t[1], @x[4], @x[5]
+       veor    @s[0], @x[1], @x[0]
+       veor    @t[3], @t[3], @s[1]
+       veor    @t[2], @t[2], @s[1]
+       vand    @s[1], @t[1], @s[0]
+       vorr    @t[1], @t[1], @s[0]
+       veor    @t[3], @t[3], @s[3]
+       veor    @t[0], @t[0], @s[1]
+       veor    @t[2], @t[2], @s[2]
+       veor    @t[1], @t[1], @s[3]
+       veor    @t[0], @t[0], @s[2]
+       vand    @s[0], @x[7], @x[3]
+       veor    @t[1], @t[1], @s[2]
+       vand    @s[1], @x[6], @x[2]
+       vand    @s[2], @x[5], @x[1]
+       vorr    @s[3], @x[4], @x[0]
+       veor    @t[3], @t[3], @s[0]
+       veor    @t[1], @t[1], @s[2]
+       veor    @t[0], @t[0], @s[3]
+       veor    @t[2], @t[2], @s[1]
+
+       @ Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3
+
+       @ new smaller inversion
+
+       vand    @s[2], @t[3], @t[1]
+       vmov    @s[0], @t[0]
+
+       veor    @s[1], @t[2], @s[2]
+       veor    @s[3], @t[0], @s[2]
+       veor    @s[2], @t[0], @s[2]     @ @s[2]=@s[3]
+
+       vbsl    @s[1], @t[1], @t[0]
+       vbsl    @s[3], @t[3], @t[2]
+       veor    @t[3], @t[3], @t[2]
+
+       vbsl    @s[0], @s[1], @s[2]
+       vbsl    @t[0], @s[2], @s[1]
+
+       vand    @s[2], @s[0], @s[3]
+       veor    @t[1], @t[1], @t[0]
+
+       veor    @s[2], @s[2], @t[3]
+___
+# output in s3, s2, s1, t1
+
+# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \t2, \t3, \t0, \t1, \s0, \s1, \s2, \s3
+
+# Mul_GF16_2 \x0, \x1, \x2, \x3, \x4, \x5, \x6, \x7, \s3, \s2, \s1, \t1, \s0, \t0, \t2, \t3
+       &Mul_GF16_2(@x,@s[3,2,1],@t[1],@s[0],@t[0,2,3]);
+
+### output msb > [x3,x2,x1,x0,x7,x6,x5,x4] < lsb
+}
+
+# AES linear components
+
+sub ShiftRows {
+my @x=@_[0..7];
+my @t=@_[8..11];
+my $mask=pop;
+$code.=<<___;
+       vldmia  $key!, {@t[0]-@t[3]}
+       veor    @t[0], @t[0], @x[0]
+       veor    @t[1], @t[1], @x[1]
+       vtbl.8  `&Dlo(@x[0])`, {@t[0]}, `&Dlo($mask)`
+       vtbl.8  `&Dhi(@x[0])`, {@t[0]}, `&Dhi($mask)`
+       vldmia  $key!, {@t[0]}
+       veor    @t[2], @t[2], @x[2]
+       vtbl.8  `&Dlo(@x[1])`, {@t[1]}, `&Dlo($mask)`
+       vtbl.8  `&Dhi(@x[1])`, {@t[1]}, `&Dhi($mask)`
+       vldmia  $key!, {@t[1]}
+       veor    @t[3], @t[3], @x[3]
+       vtbl.8  `&Dlo(@x[2])`, {@t[2]}, `&Dlo($mask)`
+       vtbl.8  `&Dhi(@x[2])`, {@t[2]}, `&Dhi($mask)`
+       vldmia  $key!, {@t[2]}
+       vtbl.8  `&Dlo(@x[3])`, {@t[3]}, `&Dlo($mask)`
+       vtbl.8  `&Dhi(@x[3])`, {@t[3]}, `&Dhi($mask)`
+       vldmia  $key!, {@t[3]}
+       veor    @t[0], @t[0], @x[4]
+       veor    @t[1], @t[1], @x[5]
+       vtbl.8  `&Dlo(@x[4])`, {@t[0]}, `&Dlo($mask)`
+       vtbl.8  `&Dhi(@x[4])`, {@t[0]}, `&Dhi($mask)`
+       veor    @t[2], @t[2], @x[6]
+       vtbl.8  `&Dlo(@x[5])`, {@t[1]}, `&Dlo($mask)`
+       vtbl.8  `&Dhi(@x[5])`, {@t[1]}, `&Dhi($mask)`
+       veor    @t[3], @t[3], @x[7]
+       vtbl.8  `&Dlo(@x[6])`, {@t[2]}, `&Dlo($mask)`
+       vtbl.8  `&Dhi(@x[6])`, {@t[2]}, `&Dhi($mask)`
+       vtbl.8  `&Dlo(@x[7])`, {@t[3]}, `&Dlo($mask)`
+       vtbl.8  `&Dhi(@x[7])`, {@t[3]}, `&Dhi($mask)`
+___
+}
+
+sub MixColumns {
+# modified to emit output in order suitable for feeding back to aesenc[last]
+my @x=@_[0..7];
+my @t=@_[8..15];
+my $inv=@_[16];        # optional
+$code.=<<___;
+       vext.8  @t[0], @x[0], @x[0], #12        @ x0 <<< 32
+       vext.8  @t[1], @x[1], @x[1], #12
+        veor   @x[0], @x[0], @t[0]             @ x0 ^ (x0 <<< 32)
+       vext.8  @t[2], @x[2], @x[2], #12
+        veor   @x[1], @x[1], @t[1]
+       vext.8  @t[3], @x[3], @x[3], #12
+        veor   @x[2], @x[2], @t[2]
+       vext.8  @t[4], @x[4], @x[4], #12
+        veor   @x[3], @x[3], @t[3]
+       vext.8  @t[5], @x[5], @x[5], #12
+        veor   @x[4], @x[4], @t[4]
+       vext.8  @t[6], @x[6], @x[6], #12
+        veor   @x[5], @x[5], @t[5]
+       vext.8  @t[7], @x[7], @x[7], #12
+        veor   @x[6], @x[6], @t[6]
+
+       veor    @t[1], @t[1], @x[0]
+        veor   @x[7], @x[7], @t[7]
+        vext.8 @x[0], @x[0], @x[0], #8         @ (x0 ^ (x0 <<< 32)) <<< 64)
+       veor    @t[2], @t[2], @x[1]
+       veor    @t[0], @t[0], @x[7]
+       veor    @t[1], @t[1], @x[7]
+        vext.8 @x[1], @x[1], @x[1], #8
+       veor    @t[5], @t[5], @x[4]
+        veor   @x[0], @x[0], @t[0]
+       veor    @t[6], @t[6], @x[5]
+        veor   @x[1], @x[1], @t[1]
+        vext.8 @t[0], @x[4], @x[4], #8
+       veor    @t[4], @t[4], @x[3]
+        vext.8 @t[1], @x[5], @x[5], #8
+       veor    @t[7], @t[7], @x[6]
+        vext.8 @x[4], @x[3], @x[3], #8
+       veor    @t[3], @t[3], @x[2]
+        vext.8 @x[5], @x[7], @x[7], #8
+       veor    @t[4], @t[4], @x[7]
+        vext.8 @x[3], @x[6], @x[6], #8
+       veor    @t[3], @t[3], @x[7]
+        vext.8 @x[6], @x[2], @x[2], #8
+       veor    @x[7], @t[1], @t[5]
+___
+$code.=<<___ if (!$inv);
+       veor    @x[2], @t[0], @t[4]
+       veor    @x[4], @x[4], @t[3]
+       veor    @x[5], @x[5], @t[7]
+       veor    @x[3], @x[3], @t[6]
+        @ vmov @x[2], @t[0]
+       veor    @x[6], @x[6], @t[2]
+        @ vmov @x[7], @t[1]
+___
+$code.=<<___ if ($inv);
+       veor    @t[3], @t[3], @x[4]
+       veor    @x[5], @x[5], @t[7]
+       veor    @x[2], @x[3], @t[6]
+       veor    @x[3], @t[0], @t[4]
+       veor    @x[4], @x[6], @t[2]
+       vmov    @x[6], @t[3]
+        @ vmov @x[7], @t[1]
+___
+}
+
+sub InvMixColumns_orig {
+my @x=@_[0..7];
+my @t=@_[8..15];
+
+$code.=<<___;
+       @ multiplication by 0x0e
+       vext.8  @t[7], @x[7], @x[7], #12
+       vmov    @t[2], @x[2]
+       veor    @x[2], @x[2], @x[5]             @ 2 5
+       veor    @x[7], @x[7], @x[5]             @ 7 5
+       vext.8  @t[0], @x[0], @x[0], #12
+       vmov    @t[5], @x[5]
+       veor    @x[5], @x[5], @x[0]             @ 5 0           [1]
+       veor    @x[0], @x[0], @x[1]             @ 0 1
+       vext.8  @t[1], @x[1], @x[1], #12
+       veor    @x[1], @x[1], @x[2]             @ 1 25
+       veor    @x[0], @x[0], @x[6]             @ 01 6          [2]
+       vext.8  @t[3], @x[3], @x[3], #12
+       veor    @x[1], @x[1], @x[3]             @ 125 3         [4]
+       veor    @x[2], @x[2], @x[0]             @ 25 016        [3]
+       veor    @x[3], @x[3], @x[7]             @ 3 75
+       veor    @x[7], @x[7], @x[6]             @ 75 6          [0]
+       vext.8  @t[6], @x[6], @x[6], #12
+       vmov    @t[4], @x[4]
+       veor    @x[6], @x[6], @x[4]             @ 6 4
+       veor    @x[4], @x[4], @x[3]             @ 4 375         [6]
+       veor    @x[3], @x[3], @x[7]             @ 375 756=36
+       veor    @x[6], @x[6], @t[5]             @ 64 5          [7]
+       veor    @x[3], @x[3], @t[2]             @ 36 2
+       vext.8  @t[5], @t[5], @t[5], #12
+       veor    @x[3], @x[3], @t[4]             @ 362 4         [5]
+___
+                                       my @y = @x[7,5,0,2,1,3,4,6];
+$code.=<<___;
+       @ multiplication by 0x0b
+       veor    @y[1], @y[1], @y[0]
+       veor    @y[0], @y[0], @t[0]
+       vext.8  @t[2], @t[2], @t[2], #12
+       veor    @y[1], @y[1], @t[1]
+       veor    @y[0], @y[0], @t[5]
+       vext.8  @t[4], @t[4], @t[4], #12
+       veor    @y[1], @y[1], @t[6]
+       veor    @y[0], @y[0], @t[7]
+       veor    @t[7], @t[7], @t[6]             @ clobber t[7]
+
+       veor    @y[3], @y[3], @t[0]
+        veor   @y[1], @y[1], @y[0]
+       vext.8  @t[0], @t[0], @t[0], #12
+       veor    @y[2], @y[2], @t[1]
+       veor    @y[4], @y[4], @t[1]
+       vext.8  @t[1], @t[1], @t[1], #12
+       veor    @y[2], @y[2], @t[2]
+       veor    @y[3], @y[3], @t[2]
+       veor    @y[5], @y[5], @t[2]
+       veor    @y[2], @y[2], @t[7]
+       vext.8  @t[2], @t[2], @t[2], #12
+       veor    @y[3], @y[3], @t[3]
+       veor    @y[6], @y[6], @t[3]
+       veor    @y[4], @y[4], @t[3]
+       veor    @y[7], @y[7], @t[4]
+       vext.8  @t[3], @t[3], @t[3], #12
+       veor    @y[5], @y[5], @t[4]
+       veor    @y[7], @y[7], @t[7]
+       veor    @t[7], @t[7], @t[5]             @ clobber t[7] even more
+       veor    @y[3], @y[3], @t[5]
+       veor    @y[4], @y[4], @t[4]
+
+       veor    @y[5], @y[5], @t[7]
+       vext.8  @t[4], @t[4], @t[4], #12
+       veor    @y[6], @y[6], @t[7]
+       veor    @y[4], @y[4], @t[7]
+
+       veor    @t[7], @t[7], @t[5]
+       vext.8  @t[5], @t[5], @t[5], #12
+
+       @ multiplication by 0x0d
+       veor    @y[4], @y[4], @y[7]
+        veor   @t[7], @t[7], @t[6]             @ restore t[7]
+       veor    @y[7], @y[7], @t[4]
+       vext.8  @t[6], @t[6], @t[6], #12
+       veor    @y[2], @y[2], @t[0]
+       veor    @y[7], @y[7], @t[5]
+       vext.8  @t[7], @t[7], @t[7], #12
+       veor    @y[2], @y[2], @t[2]
+
+       veor    @y[3], @y[3], @y[1]
+       veor    @y[1], @y[1], @t[1]
+       veor    @y[0], @y[0], @t[0]
+       veor    @y[3], @y[3], @t[0]
+       veor    @y[1], @y[1], @t[5]
+       veor    @y[0], @y[0], @t[5]
+       vext.8  @t[0], @t[0], @t[0], #12
+       veor    @y[1], @y[1], @t[7]
+       veor    @y[0], @y[0], @t[6]
+       veor    @y[3], @y[3], @y[1]
+       veor    @y[4], @y[4], @t[1]
+       vext.8  @t[1], @t[1], @t[1], #12
+
+       veor    @y[7], @y[7], @t[7]
+       veor    @y[4], @y[4], @t[2]
+       veor    @y[5], @y[5], @t[2]
+       veor    @y[2], @y[2], @t[6]
+       veor    @t[6], @t[6], @t[3]             @ clobber t[6]
+       vext.8  @t[2], @t[2], @t[2], #12
+       veor    @y[4], @y[4], @y[7]
+       veor    @y[3], @y[3], @t[6]
+
+       veor    @y[6], @y[6], @t[6]
+       veor    @y[5], @y[5], @t[5]
+       vext.8  @t[5], @t[5], @t[5], #12
+       veor    @y[6], @y[6], @t[4]
+       vext.8  @t[4], @t[4], @t[4], #12
+       veor    @y[5], @y[5], @t[6]
+       veor    @y[6], @y[6], @t[7]
+       vext.8  @t[7], @t[7], @t[7], #12
+       veor    @t[6], @t[6], @t[3]             @ restore t[6]
+       vext.8  @t[3], @t[3], @t[3], #12
+
+       @ multiplication by 0x09
+       veor    @y[4], @y[4], @y[1]
+       veor    @t[1], @t[1], @y[1]             @ t[1]=y[1]
+       veor    @t[0], @t[0], @t[5]             @ clobber t[0]
+       vext.8  @t[6], @t[6], @t[6], #12
+       veor    @t[1], @t[1], @t[5]
+       veor    @y[3], @y[3], @t[0]
+       veor    @t[0], @t[0], @y[0]             @ t[0]=y[0]
+       veor    @t[1], @t[1], @t[6]
+       veor    @t[6], @t[6], @t[7]             @ clobber t[6]
+       veor    @y[4], @y[4], @t[1]
+       veor    @y[7], @y[7], @t[4]
+       veor    @y[6], @y[6], @t[3]
+       veor    @y[5], @y[5], @t[2]
+       veor    @t[4], @t[4], @y[4]             @ t[4]=y[4]
+       veor    @t[3], @t[3], @y[3]             @ t[3]=y[3]
+       veor    @t[5], @t[5], @y[5]             @ t[5]=y[5]
+       veor    @t[2], @t[2], @y[2]             @ t[2]=y[2]
+       veor    @t[3], @t[3], @t[7]
+       veor    @XMM[5], @t[5], @t[6]
+       veor    @XMM[6], @t[6], @y[6]           @ t[6]=y[6]
+       veor    @XMM[2], @t[2], @t[6]
+       veor    @XMM[7], @t[7], @y[7]           @ t[7]=y[7]
+
+       vmov    @XMM[0], @t[0]
+       vmov    @XMM[1], @t[1]
+       @ vmov  @XMM[2], @t[2]
+       vmov    @XMM[3], @t[3]
+       vmov    @XMM[4], @t[4]
+       @ vmov  @XMM[5], @t[5]
+       @ vmov  @XMM[6], @t[6]
+       @ vmov  @XMM[7], @t[7]
+___
+}
+
+sub InvMixColumns {
+my @x=@_[0..7];
+my @t=@_[8..15];
+
+# Thanks to Jussi Kivilinna for providing pointer to
+#
+# | 0e 0b 0d 09 |   | 02 03 01 01 |   | 05 00 04 00 |
+# | 09 0e 0b 0d | = | 01 02 03 01 | x | 00 05 00 04 |
+# | 0d 09 0e 0b |   | 01 01 02 03 |   | 04 00 05 00 |
+# | 0b 0d 09 0e |   | 03 01 01 02 |   | 00 04 00 05 |
+
+$code.=<<___;
+       @ multiplication by 0x05-0x00-0x04-0x00
+       vext.8  @t[0], @x[0], @x[0], #8
+       vext.8  @t[6], @x[6], @x[6], #8
+       vext.8  @t[7], @x[7], @x[7], #8
+       veor    @t[0], @t[0], @x[0]
+       vext.8  @t[1], @x[1], @x[1], #8
+       veor    @t[6], @t[6], @x[6]
+       vext.8  @t[2], @x[2], @x[2], #8
+       veor    @t[7], @t[7], @x[7]
+       vext.8  @t[3], @x[3], @x[3], #8
+       veor    @t[1], @t[1], @x[1]
+       vext.8  @t[4], @x[4], @x[4], #8
+       veor    @t[2], @t[2], @x[2]
+       vext.8  @t[5], @x[5], @x[5], #8
+       veor    @t[3], @t[3], @x[3]
+       veor    @t[4], @t[4], @x[4]
+       veor    @t[5], @t[5], @x[5]
+
+        veor   @x[0], @x[0], @t[6]
+        veor   @x[1], @x[1], @t[6]
+        veor   @x[2], @x[2], @t[0]
+        veor   @x[4], @x[4], @t[2]
+        veor   @x[3], @x[3], @t[1]
+        veor   @x[1], @x[1], @t[7]
+        veor   @x[2], @x[2], @t[7]
+        veor   @x[4], @x[4], @t[6]
+        veor   @x[5], @x[5], @t[3]
+        veor   @x[3], @x[3], @t[6]
+        veor   @x[6], @x[6], @t[4]
+        veor   @x[4], @x[4], @t[7]
+        veor   @x[5], @x[5], @t[7]
+        veor   @x[7], @x[7], @t[5]
+___
+       &MixColumns     (@x,@t,1);      # flipped 2<->3 and 4<->6
+}
+
+sub swapmove {
+my ($a,$b,$n,$mask,$t)=@_;
+$code.=<<___;
+       vshr.u64        $t, $b, #$n
+       veor            $t, $t, $a
+       vand            $t, $t, $mask
+       veor            $a, $a, $t
+       vshl.u64        $t, $t, #$n
+       veor            $b, $b, $t
+___
+}
+sub swapmove2x {
+my ($a0,$b0,$a1,$b1,$n,$mask,$t0,$t1)=@_;
+$code.=<<___;
+       vshr.u64        $t0, $b0, #$n
+        vshr.u64       $t1, $b1, #$n
+       veor            $t0, $t0, $a0
+        veor           $t1, $t1, $a1
+       vand            $t0, $t0, $mask
+        vand           $t1, $t1, $mask
+       veor            $a0, $a0, $t0
+       vshl.u64        $t0, $t0, #$n
+        veor           $a1, $a1, $t1
+        vshl.u64       $t1, $t1, #$n
+       veor            $b0, $b0, $t0
+        veor           $b1, $b1, $t1
+___
+}
+
+sub bitslice {
+my @x=reverse(@_[0..7]);
+my ($t0,$t1,$t2,$t3)=@_[8..11];
+$code.=<<___;
+       vmov.i8 $t0,#0x55                       @ compose .LBS0
+       vmov.i8 $t1,#0x33                       @ compose .LBS1
+___
+       &swapmove2x(@x[0,1,2,3],1,$t0,$t2,$t3);
+       &swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
+$code.=<<___;
+       vmov.i8 $t0,#0x0f                       @ compose .LBS2
+___
+       &swapmove2x(@x[0,2,1,3],2,$t1,$t2,$t3);
+       &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
+
+       &swapmove2x(@x[0,4,1,5],4,$t0,$t2,$t3);
+       &swapmove2x(@x[2,6,3,7],4,$t0,$t2,$t3);
+}
+
+$code.=<<___;
+#ifndef __KERNEL__
+# include "arm_arch.h"
+
+# define VFP_ABI_PUSH  vstmdb  sp!,{d8-d15}
+# define VFP_ABI_POP   vldmia  sp!,{d8-d15}
+# define VFP_ABI_FRAME 0x40
+#else
+# define VFP_ABI_PUSH
+# define VFP_ABI_POP
+# define VFP_ABI_FRAME 0
+# define BSAES_ASM_EXTENDED_KEY
+# define XTS_CHAIN_TWEAK
+# define __ARM_ARCH__ __LINUX_ARM_ARCH__
+#endif
+
+#ifdef __thumb__
+# define adrl adr
+#endif
+
+#if __ARM_ARCH__>=7
+.text
+.syntax        unified         @ ARMv7-capable assembler is expected to handle this
+#ifdef __thumb2__
+.thumb
+#else
+.code   32
+#endif
+
+.fpu   neon
+
+.type  _bsaes_decrypt8,%function
+.align 4
+_bsaes_decrypt8:
+       adr     $const,_bsaes_decrypt8
+       vldmia  $key!, {@XMM[9]}                @ round 0 key
+       add     $const,$const,#.LM0ISR-_bsaes_decrypt8
+
+       vldmia  $const!, {@XMM[8]}              @ .LM0ISR
+       veor    @XMM[10], @XMM[0], @XMM[9]      @ xor with round0 key
+       veor    @XMM[11], @XMM[1], @XMM[9]
+        vtbl.8 `&Dlo(@XMM[0])`, {@XMM[10]}, `&Dlo(@XMM[8])`
+        vtbl.8 `&Dhi(@XMM[0])`, {@XMM[10]}, `&Dhi(@XMM[8])`
+       veor    @XMM[12], @XMM[2], @XMM[9]
+        vtbl.8 `&Dlo(@XMM[1])`, {@XMM[11]}, `&Dlo(@XMM[8])`
+        vtbl.8 `&Dhi(@XMM[1])`, {@XMM[11]}, `&Dhi(@XMM[8])`
+       veor    @XMM[13], @XMM[3], @XMM[9]
+        vtbl.8 `&Dlo(@XMM[2])`, {@XMM[12]}, `&Dlo(@XMM[8])`
+        vtbl.8 `&Dhi(@XMM[2])`, {@XMM[12]}, `&Dhi(@XMM[8])`
+       veor    @XMM[14], @XMM[4], @XMM[9]
+        vtbl.8 `&Dlo(@XMM[3])`, {@XMM[13]}, `&Dlo(@XMM[8])`
+        vtbl.8 `&Dhi(@XMM[3])`, {@XMM[13]}, `&Dhi(@XMM[8])`
+       veor    @XMM[15], @XMM[5], @XMM[9]
+        vtbl.8 `&Dlo(@XMM[4])`, {@XMM[14]}, `&Dlo(@XMM[8])`
+        vtbl.8 `&Dhi(@XMM[4])`, {@XMM[14]}, `&Dhi(@XMM[8])`
+       veor    @XMM[10], @XMM[6], @XMM[9]
+        vtbl.8 `&Dlo(@XMM[5])`, {@XMM[15]}, `&Dlo(@XMM[8])`
+        vtbl.8 `&Dhi(@XMM[5])`, {@XMM[15]}, `&Dhi(@XMM[8])`
+       veor    @XMM[11], @XMM[7], @XMM[9]
+        vtbl.8 `&Dlo(@XMM[6])`, {@XMM[10]}, `&Dlo(@XMM[8])`
+        vtbl.8 `&Dhi(@XMM[6])`, {@XMM[10]}, `&Dhi(@XMM[8])`
+        vtbl.8 `&Dlo(@XMM[7])`, {@XMM[11]}, `&Dlo(@XMM[8])`
+        vtbl.8 `&Dhi(@XMM[7])`, {@XMM[11]}, `&Dhi(@XMM[8])`
+___
+       &bitslice       (@XMM[0..7, 8..11]);
+$code.=<<___;
+       sub     $rounds,$rounds,#1
+       b       .Ldec_sbox
+.align 4
+.Ldec_loop:
+___
+       &ShiftRows      (@XMM[0..7, 8..12]);
+$code.=".Ldec_sbox:\n";
+       &InvSbox        (@XMM[0..7, 8..15]);
+$code.=<<___;
+       subs    $rounds,$rounds,#1
+       bcc     .Ldec_done
+___
+       &InvMixColumns  (@XMM[0,1,6,4,2,7,3,5, 8..15]);
+$code.=<<___;
+       vldmia  $const, {@XMM[12]}              @ .LISR
+       ite     eq                              @ Thumb2 thing, sanity check in ARM
+       addeq   $const,$const,#0x10
+       bne     .Ldec_loop
+       vldmia  $const, {@XMM[12]}              @ .LISRM0
+       b       .Ldec_loop
+.align 4
+.Ldec_done:
+___
+       &bitslice       (@XMM[0,1,6,4,2,7,3,5, 8..11]);
+$code.=<<___;
+       vldmia  $key, {@XMM[8]}                 @ last round key
+       veor    @XMM[6], @XMM[6], @XMM[8]
+       veor    @XMM[4], @XMM[4], @XMM[8]
+       veor    @XMM[2], @XMM[2], @XMM[8]
+       veor    @XMM[7], @XMM[7], @XMM[8]
+       veor    @XMM[3], @XMM[3], @XMM[8]
+       veor    @XMM[5], @XMM[5], @XMM[8]
+       veor    @XMM[0], @XMM[0], @XMM[8]
+       veor    @XMM[1], @XMM[1], @XMM[8]
+       bx      lr
+.size  _bsaes_decrypt8,.-_bsaes_decrypt8
+
+.type  _bsaes_const,%object
+.align 6
+_bsaes_const:
+.LM0ISR:       @ InvShiftRows constants
+       .quad   0x0a0e0206070b0f03, 0x0004080c0d010509
+.LISR:
+       .quad   0x0504070602010003, 0x0f0e0d0c080b0a09
+.LISRM0:
+       .quad   0x01040b0e0205080f, 0x0306090c00070a0d
+.LM0SR:                @ ShiftRows constants
+       .quad   0x0a0e02060f03070b, 0x0004080c05090d01
+.LSR:
+       .quad   0x0504070600030201, 0x0f0e0d0c0a09080b
+.LSRM0:
+       .quad   0x0304090e00050a0f, 0x01060b0c0207080d
+.LM0:
+       .quad   0x02060a0e03070b0f, 0x0004080c0105090d
+.LREVM0SR:
+       .quad   0x090d01050c000408, 0x03070b0f060a0e02
+.asciz "Bit-sliced AES for NEON, CRYPTOGAMS by <appro\@openssl.org>"
+.align 6
+.size  _bsaes_const,.-_bsaes_const
+
+.type  _bsaes_encrypt8,%function
+.align 4
+_bsaes_encrypt8:
+       adr     $const,_bsaes_encrypt8
+       vldmia  $key!, {@XMM[9]}                @ round 0 key
+       sub     $const,$const,#_bsaes_encrypt8-.LM0SR
+
+       vldmia  $const!, {@XMM[8]}              @ .LM0SR
+_bsaes_encrypt8_alt:
+       veor    @XMM[10], @XMM[0], @XMM[9]      @ xor with round0 key
+       veor    @XMM[11], @XMM[1], @XMM[9]
+        vtbl.8 `&Dlo(@XMM[0])`, {@XMM[10]}, `&Dlo(@XMM[8])`
+        vtbl.8 `&Dhi(@XMM[0])`, {@XMM[10]}, `&Dhi(@XMM[8])`
+       veor    @XMM[12], @XMM[2], @XMM[9]
+        vtbl.8 `&Dlo(@XMM[1])`, {@XMM[11]}, `&Dlo(@XMM[8])`
+        vtbl.8 `&Dhi(@XMM[1])`, {@XMM[11]}, `&Dhi(@XMM[8])`
+       veor    @XMM[13], @XMM[3], @XMM[9]
+        vtbl.8 `&Dlo(@XMM[2])`, {@XMM[12]}, `&Dlo(@XMM[8])`
+        vtbl.8 `&Dhi(@XMM[2])`, {@XMM[12]}, `&Dhi(@XMM[8])`
+       veor    @XMM[14], @XMM[4], @XMM[9]
+        vtbl.8 `&Dlo(@XMM[3])`, {@XMM[13]}, `&Dlo(@XMM[8])`
+        vtbl.8 `&Dhi(@XMM[3])`, {@XMM[13]}, `&Dhi(@XMM[8])`
+       veor    @XMM[15], @XMM[5], @XMM[9]
+        vtbl.8 `&Dlo(@XMM[4])`, {@XMM[14]}, `&Dlo(@XMM[8])`
+        vtbl.8 `&Dhi(@XMM[4])`, {@XMM[14]}, `&Dhi(@XMM[8])`
+       veor    @XMM[10], @XMM[6], @XMM[9]
+        vtbl.8 `&Dlo(@XMM[5])`, {@XMM[15]}, `&Dlo(@XMM[8])`
+        vtbl.8 `&Dhi(@XMM[5])`, {@XMM[15]}, `&Dhi(@XMM[8])`
+       veor    @XMM[11], @XMM[7], @XMM[9]
+        vtbl.8 `&Dlo(@XMM[6])`, {@XMM[10]}, `&Dlo(@XMM[8])`
+        vtbl.8 `&Dhi(@XMM[6])`, {@XMM[10]}, `&Dhi(@XMM[8])`
+        vtbl.8 `&Dlo(@XMM[7])`, {@XMM[11]}, `&Dlo(@XMM[8])`
+        vtbl.8 `&Dhi(@XMM[7])`, {@XMM[11]}, `&Dhi(@XMM[8])`
+_bsaes_encrypt8_bitslice:
+___
+       &bitslice       (@XMM[0..7, 8..11]);
+$code.=<<___;
+       sub     $rounds,$rounds,#1
+       b       .Lenc_sbox
+.align 4
+.Lenc_loop:
+___
+       &ShiftRows      (@XMM[0..7, 8..12]);
+$code.=".Lenc_sbox:\n";
+       &Sbox           (@XMM[0..7, 8..15]);
+$code.=<<___;
+       subs    $rounds,$rounds,#1
+       bcc     .Lenc_done
+___
+       &MixColumns     (@XMM[0,1,4,6,3,7,2,5, 8..15]);
+$code.=<<___;
+       vldmia  $const, {@XMM[12]}              @ .LSR
+       ite     eq                              @ Thumb2 thing, samity check in ARM
+       addeq   $const,$const,#0x10
+       bne     .Lenc_loop
+       vldmia  $const, {@XMM[12]}              @ .LSRM0
+       b       .Lenc_loop
+.align 4
+.Lenc_done:
+___
+       # output in lsb > [t0, t1, t4, t6, t3, t7, t2, t5] < msb
+       &bitslice       (@XMM[0,1,4,6,3,7,2,5, 8..11]);
+$code.=<<___;
+       vldmia  $key, {@XMM[8]}                 @ last round key
+       veor    @XMM[4], @XMM[4], @XMM[8]
+       veor    @XMM[6], @XMM[6], @XMM[8]
+       veor    @XMM[3], @XMM[3], @XMM[8]
+       veor    @XMM[7], @XMM[7], @XMM[8]
+       veor    @XMM[2], @XMM[2], @XMM[8]
+       veor    @XMM[5], @XMM[5], @XMM[8]
+       veor    @XMM[0], @XMM[0], @XMM[8]
+       veor    @XMM[1], @XMM[1], @XMM[8]
+       bx      lr
+.size  _bsaes_encrypt8,.-_bsaes_encrypt8
+___
+}
+{
+my ($out,$inp,$rounds,$const)=("r12","r4","r5","r6");
+
+sub bitslice_key {
+my @x=reverse(@_[0..7]);
+my ($bs0,$bs1,$bs2,$t2,$t3)=@_[8..12];
+
+       &swapmove       (@x[0,1],1,$bs0,$t2,$t3);
+$code.=<<___;
+       @ &swapmove(@x[2,3],1,$t0,$t2,$t3);
+       vmov    @x[2], @x[0]
+       vmov    @x[3], @x[1]
+___
+       #&swapmove2x(@x[4,5,6,7],1,$t0,$t2,$t3);
+
+       &swapmove2x     (@x[0,2,1,3],2,$bs1,$t2,$t3);
+$code.=<<___;
+       @ &swapmove2x(@x[4,6,5,7],2,$t1,$t2,$t3);
+       vmov    @x[4], @x[0]
+       vmov    @x[6], @x[2]
+       vmov    @x[5], @x[1]
+       vmov    @x[7], @x[3]
+___
+       &swapmove2x     (@x[0,4,1,5],4,$bs2,$t2,$t3);
+       &swapmove2x     (@x[2,6,3,7],4,$bs2,$t2,$t3);
+}
+
+$code.=<<___;
+.type  _bsaes_key_convert,%function
+.align 4
+_bsaes_key_convert:
+       adr     $const,_bsaes_key_convert
+       vld1.8  {@XMM[7]},  [$inp]!             @ load round 0 key
+       sub     $const,$const,#_bsaes_key_convert-.LM0
+       vld1.8  {@XMM[15]}, [$inp]!             @ load round 1 key
+
+       vmov.i8 @XMM[8],  #0x01                 @ bit masks
+       vmov.i8 @XMM[9],  #0x02
+       vmov.i8 @XMM[10], #0x04
+       vmov.i8 @XMM[11], #0x08
+       vmov.i8 @XMM[12], #0x10
+       vmov.i8 @XMM[13], #0x20
+       vldmia  $const, {@XMM[14]}              @ .LM0
+
+#ifdef __ARMEL__
+       vrev32.8        @XMM[7],  @XMM[7]
+       vrev32.8        @XMM[15], @XMM[15]
+#endif
+       sub     $rounds,$rounds,#1
+       vstmia  $out!, {@XMM[7]}                @ save round 0 key
+       b       .Lkey_loop
+
+.align 4
+.Lkey_loop:
+       vtbl.8  `&Dlo(@XMM[7])`,{@XMM[15]},`&Dlo(@XMM[14])`
+       vtbl.8  `&Dhi(@XMM[7])`,{@XMM[15]},`&Dhi(@XMM[14])`
+       vmov.i8 @XMM[6],  #0x40
+       vmov.i8 @XMM[15], #0x80
+
+       vtst.8  @XMM[0], @XMM[7], @XMM[8]
+       vtst.8  @XMM[1], @XMM[7], @XMM[9]
+       vtst.8  @XMM[2], @XMM[7], @XMM[10]
+       vtst.8  @XMM[3], @XMM[7], @XMM[11]
+       vtst.8  @XMM[4], @XMM[7], @XMM[12]
+       vtst.8  @XMM[5], @XMM[7], @XMM[13]
+       vtst.8  @XMM[6], @XMM[7], @XMM[6]
+       vtst.8  @XMM[7], @XMM[7], @XMM[15]
+       vld1.8  {@XMM[15]}, [$inp]!             @ load next round key
+       vmvn    @XMM[0], @XMM[0]                @ "pnot"
+       vmvn    @XMM[1], @XMM[1]
+       vmvn    @XMM[5], @XMM[5]
+       vmvn    @XMM[6], @XMM[6]
+#ifdef __ARMEL__
+       vrev32.8        @XMM[15], @XMM[15]
+#endif
+       subs    $rounds,$rounds,#1
+       vstmia  $out!,{@XMM[0]-@XMM[7]}         @ write bit-sliced round key
+       bne     .Lkey_loop
+
+       vmov.i8 @XMM[7],#0x63                   @ compose .L63
+       @ don't save last round key
+       bx      lr
+.size  _bsaes_key_convert,.-_bsaes_key_convert
+___
+}
+
+if (0) {               # following four functions are unsupported interface
+                       # used for benchmarking...
+$code.=<<___;
+.globl bsaes_enc_key_convert
+.type  bsaes_enc_key_convert,%function
+.align 4
+bsaes_enc_key_convert:
+       stmdb   sp!,{r4-r6,lr}
+       vstmdb  sp!,{d8-d15}            @ ABI specification says so
+
+       ldr     r5,[$inp,#240]                  @ pass rounds
+       mov     r4,$inp                         @ pass key
+       mov     r12,$out                        @ pass key schedule
+       bl      _bsaes_key_convert
+       veor    @XMM[7],@XMM[7],@XMM[15]        @ fix up last round key
+       vstmia  r12, {@XMM[7]}                  @ save last round key
+
+       vldmia  sp!,{d8-d15}
+       ldmia   sp!,{r4-r6,pc}
+.size  bsaes_enc_key_convert,.-bsaes_enc_key_convert
+
+.globl bsaes_encrypt_128
+.type  bsaes_encrypt_128,%function
+.align 4
+bsaes_encrypt_128:
+       stmdb   sp!,{r4-r6,lr}
+       vstmdb  sp!,{d8-d15}            @ ABI specification says so
+.Lenc128_loop:
+       vld1.8  {@XMM[0]-@XMM[1]}, [$inp]!      @ load input
+       vld1.8  {@XMM[2]-@XMM[3]}, [$inp]!
+       mov     r4,$key                         @ pass the key
+       vld1.8  {@XMM[4]-@XMM[5]}, [$inp]!
+       mov     r5,#10                          @ pass rounds
+       vld1.8  {@XMM[6]-@XMM[7]}, [$inp]!
+
+       bl      _bsaes_encrypt8
+
+       vst1.8  {@XMM[0]-@XMM[1]}, [$out]!      @ write output
+       vst1.8  {@XMM[4]}, [$out]!
+       vst1.8  {@XMM[6]}, [$out]!
+       vst1.8  {@XMM[3]}, [$out]!
+       vst1.8  {@XMM[7]}, [$out]!
+       vst1.8  {@XMM[2]}, [$out]!
+       subs    $len,$len,#0x80
+       vst1.8  {@XMM[5]}, [$out]!
+       bhi     .Lenc128_loop
+
+       vldmia  sp!,{d8-d15}
+       ldmia   sp!,{r4-r6,pc}
+.size  bsaes_encrypt_128,.-bsaes_encrypt_128
+
+.globl bsaes_dec_key_convert
+.type  bsaes_dec_key_convert,%function
+.align 4
+bsaes_dec_key_convert:
+       stmdb   sp!,{r4-r6,lr}
+       vstmdb  sp!,{d8-d15}            @ ABI specification says so
+
+       ldr     r5,[$inp,#240]                  @ pass rounds
+       mov     r4,$inp                         @ pass key
+       mov     r12,$out                        @ pass key schedule
+       bl      _bsaes_key_convert
+       vldmia  $out, {@XMM[6]}
+       vstmia  r12,  {@XMM[15]}                @ save last round key
+       veor    @XMM[7], @XMM[7], @XMM[6]       @ fix up round 0 key
+       vstmia  $out, {@XMM[7]}
+
+       vldmia  sp!,{d8-d15}
+       ldmia   sp!,{r4-r6,pc}
+.size  bsaes_dec_key_convert,.-bsaes_dec_key_convert
+
+.globl bsaes_decrypt_128
+.type  bsaes_decrypt_128,%function
+.align 4
+bsaes_decrypt_128:
+       stmdb   sp!,{r4-r6,lr}
+       vstmdb  sp!,{d8-d15}            @ ABI specification says so
+.Ldec128_loop:
+       vld1.8  {@XMM[0]-@XMM[1]}, [$inp]!      @ load input
+       vld1.8  {@XMM[2]-@XMM[3]}, [$inp]!
+       mov     r4,$key                         @ pass the key
+       vld1.8  {@XMM[4]-@XMM[5]}, [$inp]!
+       mov     r5,#10                          @ pass rounds
+       vld1.8  {@XMM[6]-@XMM[7]}, [$inp]!
+
+       bl      _bsaes_decrypt8
+
+       vst1.8  {@XMM[0]-@XMM[1]}, [$out]!      @ write output
+       vst1.8  {@XMM[6]}, [$out]!
+       vst1.8  {@XMM[4]}, [$out]!
+       vst1.8  {@XMM[2]}, [$out]!
+       vst1.8  {@XMM[7]}, [$out]!
+       vst1.8  {@XMM[3]}, [$out]!
+       subs    $len,$len,#0x80
+       vst1.8  {@XMM[5]}, [$out]!
+       bhi     .Ldec128_loop
+
+       vldmia  sp!,{d8-d15}
+       ldmia   sp!,{r4-r6,pc}
+.size  bsaes_decrypt_128,.-bsaes_decrypt_128
+___
+}
+{
+my ($inp,$out,$len,$key, $ivp,$fp,$rounds)=map("r$_",(0..3,8..10));
+my ($keysched)=("sp");
+
+$code.=<<___;
+.extern AES_cbc_encrypt
+.extern AES_decrypt
+
+.global        bsaes_cbc_encrypt
+.type  bsaes_cbc_encrypt,%function
+.align 5
+bsaes_cbc_encrypt:
+#ifndef        __KERNEL__
+       cmp     $len, #128
+#ifndef        __thumb__
+       blo     AES_cbc_encrypt
+#else
+       bhs     1f
+       b       AES_cbc_encrypt
+1:
+#endif
+#endif
+
+       @ it is up to the caller to make sure we are called with enc == 0
+
+       mov     ip, sp
+       stmdb   sp!, {r4-r10, lr}
+       VFP_ABI_PUSH
+       ldr     $ivp, [ip]                      @ IV is 1st arg on the stack
+       mov     $len, $len, lsr#4               @ len in 16 byte blocks
+       sub     sp, #0x10                       @ scratch space to carry over the IV
+       mov     $fp, sp                         @ save sp
+
+       ldr     $rounds, [$key, #240]           @ get # of rounds
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       @ allocate the key schedule on the stack
+       sub     r12, sp, $rounds, lsl#7         @ 128 bytes per inner round key
+       add     r12, #`128-32`                  @ sifze of bit-slices key schedule
+
+       @ populate the key schedule
+       mov     r4, $key                        @ pass key
+       mov     r5, $rounds                     @ pass # of rounds
+       mov     sp, r12                         @ sp is $keysched
+       bl      _bsaes_key_convert
+       vldmia  $keysched, {@XMM[6]}
+       vstmia  r12,  {@XMM[15]}                @ save last round key
+       veor    @XMM[7], @XMM[7], @XMM[6]       @ fix up round 0 key
+       vstmia  $keysched, {@XMM[7]}
+#else
+       ldr     r12, [$key, #244]
+       eors    r12, #1
+       beq     0f
+
+       @ populate the key schedule
+       str     r12, [$key, #244]
+       mov     r4, $key                        @ pass key
+       mov     r5, $rounds                     @ pass # of rounds
+       add     r12, $key, #248                 @ pass key schedule
+       bl      _bsaes_key_convert
+       add     r4, $key, #248
+       vldmia  r4, {@XMM[6]}
+       vstmia  r12, {@XMM[15]}                 @ save last round key
+       veor    @XMM[7], @XMM[7], @XMM[6]       @ fix up round 0 key
+       vstmia  r4, {@XMM[7]}
+
+.align 2
+0:
+#endif
+
+       vld1.8  {@XMM[15]}, [$ivp]              @ load IV
+       b       .Lcbc_dec_loop
+
+.align 4
+.Lcbc_dec_loop:
+       subs    $len, $len, #0x8
+       bmi     .Lcbc_dec_loop_finish
+
+       vld1.8  {@XMM[0]-@XMM[1]}, [$inp]!      @ load input
+       vld1.8  {@XMM[2]-@XMM[3]}, [$inp]!
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       mov     r4, $keysched                   @ pass the key
+#else
+       add     r4, $key, #248
+#endif
+       vld1.8  {@XMM[4]-@XMM[5]}, [$inp]!
+       mov     r5, $rounds
+       vld1.8  {@XMM[6]-@XMM[7]}, [$inp]
+       sub     $inp, $inp, #0x60
+       vstmia  $fp, {@XMM[15]}                 @ put aside IV
+
+       bl      _bsaes_decrypt8
+
+       vldmia  $fp, {@XMM[14]}                 @ reload IV
+       vld1.8  {@XMM[8]-@XMM[9]}, [$inp]!      @ reload input
+       veor    @XMM[0], @XMM[0], @XMM[14]      @ ^= IV
+       vld1.8  {@XMM[10]-@XMM[11]}, [$inp]!
+       veor    @XMM[1], @XMM[1], @XMM[8]
+       veor    @XMM[6], @XMM[6], @XMM[9]
+       vld1.8  {@XMM[12]-@XMM[13]}, [$inp]!
+       veor    @XMM[4], @XMM[4], @XMM[10]
+       veor    @XMM[2], @XMM[2], @XMM[11]
+       vld1.8  {@XMM[14]-@XMM[15]}, [$inp]!
+       veor    @XMM[7], @XMM[7], @XMM[12]
+       vst1.8  {@XMM[0]-@XMM[1]}, [$out]!      @ write output
+       veor    @XMM[3], @XMM[3], @XMM[13]
+       vst1.8  {@XMM[6]}, [$out]!
+       veor    @XMM[5], @XMM[5], @XMM[14]
+       vst1.8  {@XMM[4]}, [$out]!
+       vst1.8  {@XMM[2]}, [$out]!
+       vst1.8  {@XMM[7]}, [$out]!
+       vst1.8  {@XMM[3]}, [$out]!
+       vst1.8  {@XMM[5]}, [$out]!
+
+       b       .Lcbc_dec_loop
+
+.Lcbc_dec_loop_finish:
+       adds    $len, $len, #8
+       beq     .Lcbc_dec_done
+
+       vld1.8  {@XMM[0]}, [$inp]!              @ load input
+       cmp     $len, #2
+       blo     .Lcbc_dec_one
+       vld1.8  {@XMM[1]}, [$inp]!
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       mov     r4, $keysched                   @ pass the key
+#else
+       add     r4, $key, #248
+#endif
+       mov     r5, $rounds
+       vstmia  $fp, {@XMM[15]}                 @ put aside IV
+       beq     .Lcbc_dec_two
+       vld1.8  {@XMM[2]}, [$inp]!
+       cmp     $len, #4
+       blo     .Lcbc_dec_three
+       vld1.8  {@XMM[3]}, [$inp]!
+       beq     .Lcbc_dec_four
+       vld1.8  {@XMM[4]}, [$inp]!
+       cmp     $len, #6
+       blo     .Lcbc_dec_five
+       vld1.8  {@XMM[5]}, [$inp]!
+       beq     .Lcbc_dec_six
+       vld1.8  {@XMM[6]}, [$inp]!
+       sub     $inp, $inp, #0x70
+
+       bl      _bsaes_decrypt8
+
+       vldmia  $fp, {@XMM[14]}                 @ reload IV
+       vld1.8  {@XMM[8]-@XMM[9]}, [$inp]!      @ reload input
+       veor    @XMM[0], @XMM[0], @XMM[14]      @ ^= IV
+       vld1.8  {@XMM[10]-@XMM[11]}, [$inp]!
+       veor    @XMM[1], @XMM[1], @XMM[8]
+       veor    @XMM[6], @XMM[6], @XMM[9]
+       vld1.8  {@XMM[12]-@XMM[13]}, [$inp]!
+       veor    @XMM[4], @XMM[4], @XMM[10]
+       veor    @XMM[2], @XMM[2], @XMM[11]
+       vld1.8  {@XMM[15]}, [$inp]!
+       veor    @XMM[7], @XMM[7], @XMM[12]
+       vst1.8  {@XMM[0]-@XMM[1]}, [$out]!      @ write output
+       veor    @XMM[3], @XMM[3], @XMM[13]
+       vst1.8  {@XMM[6]}, [$out]!
+       vst1.8  {@XMM[4]}, [$out]!
+       vst1.8  {@XMM[2]}, [$out]!
+       vst1.8  {@XMM[7]}, [$out]!
+       vst1.8  {@XMM[3]}, [$out]!
+       b       .Lcbc_dec_done
+.align 4
+.Lcbc_dec_six:
+       sub     $inp, $inp, #0x60
+       bl      _bsaes_decrypt8
+       vldmia  $fp,{@XMM[14]}                  @ reload IV
+       vld1.8  {@XMM[8]-@XMM[9]}, [$inp]!      @ reload input
+       veor    @XMM[0], @XMM[0], @XMM[14]      @ ^= IV
+       vld1.8  {@XMM[10]-@XMM[11]}, [$inp]!
+       veor    @XMM[1], @XMM[1], @XMM[8]
+       veor    @XMM[6], @XMM[6], @XMM[9]
+       vld1.8  {@XMM[12]}, [$inp]!
+       veor    @XMM[4], @XMM[4], @XMM[10]
+       veor    @XMM[2], @XMM[2], @XMM[11]
+       vld1.8  {@XMM[15]}, [$inp]!
+       veor    @XMM[7], @XMM[7], @XMM[12]
+       vst1.8  {@XMM[0]-@XMM[1]}, [$out]!      @ write output
+       vst1.8  {@XMM[6]}, [$out]!
+       vst1.8  {@XMM[4]}, [$out]!
+       vst1.8  {@XMM[2]}, [$out]!
+       vst1.8  {@XMM[7]}, [$out]!
+       b       .Lcbc_dec_done
+.align 4
+.Lcbc_dec_five:
+       sub     $inp, $inp, #0x50
+       bl      _bsaes_decrypt8
+       vldmia  $fp, {@XMM[14]}                 @ reload IV
+       vld1.8  {@XMM[8]-@XMM[9]}, [$inp]!      @ reload input
+       veor    @XMM[0], @XMM[0], @XMM[14]      @ ^= IV
+       vld1.8  {@XMM[10]-@XMM[11]}, [$inp]!
+       veor    @XMM[1], @XMM[1], @XMM[8]
+       veor    @XMM[6], @XMM[6], @XMM[9]
+       vld1.8  {@XMM[15]}, [$inp]!
+       veor    @XMM[4], @XMM[4], @XMM[10]
+       vst1.8  {@XMM[0]-@XMM[1]}, [$out]!      @ write output
+       veor    @XMM[2], @XMM[2], @XMM[11]
+       vst1.8  {@XMM[6]}, [$out]!
+       vst1.8  {@XMM[4]}, [$out]!
+       vst1.8  {@XMM[2]}, [$out]!
+       b       .Lcbc_dec_done
+.align 4
+.Lcbc_dec_four:
+       sub     $inp, $inp, #0x40
+       bl      _bsaes_decrypt8
+       vldmia  $fp, {@XMM[14]}                 @ reload IV
+       vld1.8  {@XMM[8]-@XMM[9]}, [$inp]!      @ reload input
+       veor    @XMM[0], @XMM[0], @XMM[14]      @ ^= IV
+       vld1.8  {@XMM[10]}, [$inp]!
+       veor    @XMM[1], @XMM[1], @XMM[8]
+       veor    @XMM[6], @XMM[6], @XMM[9]
+       vld1.8  {@XMM[15]}, [$inp]!
+       veor    @XMM[4], @XMM[4], @XMM[10]
+       vst1.8  {@XMM[0]-@XMM[1]}, [$out]!      @ write output
+       vst1.8  {@XMM[6]}, [$out]!
+       vst1.8  {@XMM[4]}, [$out]!
+       b       .Lcbc_dec_done
+.align 4
+.Lcbc_dec_three:
+       sub     $inp, $inp, #0x30
+       bl      _bsaes_decrypt8
+       vldmia  $fp, {@XMM[14]}                 @ reload IV
+       vld1.8  {@XMM[8]-@XMM[9]}, [$inp]!      @ reload input
+       veor    @XMM[0], @XMM[0], @XMM[14]      @ ^= IV
+       vld1.8  {@XMM[15]}, [$inp]!
+       veor    @XMM[1], @XMM[1], @XMM[8]
+       veor    @XMM[6], @XMM[6], @XMM[9]
+       vst1.8  {@XMM[0]-@XMM[1]}, [$out]!      @ write output
+       vst1.8  {@XMM[6]}, [$out]!
+       b       .Lcbc_dec_done
+.align 4
+.Lcbc_dec_two:
+       sub     $inp, $inp, #0x20
+       bl      _bsaes_decrypt8
+       vldmia  $fp, {@XMM[14]}                 @ reload IV
+       vld1.8  {@XMM[8]}, [$inp]!              @ reload input
+       veor    @XMM[0], @XMM[0], @XMM[14]      @ ^= IV
+       vld1.8  {@XMM[15]}, [$inp]!             @ reload input
+       veor    @XMM[1], @XMM[1], @XMM[8]
+       vst1.8  {@XMM[0]-@XMM[1]}, [$out]!      @ write output
+       b       .Lcbc_dec_done
+.align 4
+.Lcbc_dec_one:
+       sub     $inp, $inp, #0x10
+       mov     $rounds, $out                   @ save original out pointer
+       mov     $out, $fp                       @ use the iv scratch space as out buffer
+       mov     r2, $key
+       vmov    @XMM[4],@XMM[15]                @ just in case ensure that IV
+       vmov    @XMM[5],@XMM[0]                 @ and input are preserved
+       bl      AES_decrypt
+       vld1.8  {@XMM[0]}, [$fp,:64]            @ load result
+       veor    @XMM[0], @XMM[0], @XMM[4]       @ ^= IV
+       vmov    @XMM[15], @XMM[5]               @ @XMM[5] holds input
+       vst1.8  {@XMM[0]}, [$rounds]            @ write output
+
+.Lcbc_dec_done:
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       vmov.i32        q0, #0
+       vmov.i32        q1, #0
+.Lcbc_dec_bzero:                               @ wipe key schedule [if any]
+       vstmia          $keysched!, {q0-q1}
+       cmp             $keysched, $fp
+       bne             .Lcbc_dec_bzero
+#endif
+
+       mov     sp, $fp
+       add     sp, #0x10                       @ add sp,$fp,#0x10 is no good for thumb
+       vst1.8  {@XMM[15]}, [$ivp]              @ return IV
+       VFP_ABI_POP
+       ldmia   sp!, {r4-r10, pc}
+.size  bsaes_cbc_encrypt,.-bsaes_cbc_encrypt
+___
+}
+{
+my ($inp,$out,$len,$key, $ctr,$fp,$rounds)=(map("r$_",(0..3,8..10)));
+my $const = "r6";      # shared with _bsaes_encrypt8_alt
+my $keysched = "sp";
+
+$code.=<<___;
+.extern        AES_encrypt
+.global        bsaes_ctr32_encrypt_blocks
+.type  bsaes_ctr32_encrypt_blocks,%function
+.align 5
+bsaes_ctr32_encrypt_blocks:
+       cmp     $len, #8                        @ use plain AES for
+       blo     .Lctr_enc_short                 @ small sizes
+
+       mov     ip, sp
+       stmdb   sp!, {r4-r10, lr}
+       VFP_ABI_PUSH
+       ldr     $ctr, [ip]                      @ ctr is 1st arg on the stack
+       sub     sp, sp, #0x10                   @ scratch space to carry over the ctr
+       mov     $fp, sp                         @ save sp
+
+       ldr     $rounds, [$key, #240]           @ get # of rounds
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       @ allocate the key schedule on the stack
+       sub     r12, sp, $rounds, lsl#7         @ 128 bytes per inner round key
+       add     r12, #`128-32`                  @ size of bit-sliced key schedule
+
+       @ populate the key schedule
+       mov     r4, $key                        @ pass key
+       mov     r5, $rounds                     @ pass # of rounds
+       mov     sp, r12                         @ sp is $keysched
+       bl      _bsaes_key_convert
+       veor    @XMM[7],@XMM[7],@XMM[15]        @ fix up last round key
+       vstmia  r12, {@XMM[7]}                  @ save last round key
+
+       vld1.8  {@XMM[0]}, [$ctr]               @ load counter
+       add     $ctr, $const, #.LREVM0SR-.LM0   @ borrow $ctr
+       vldmia  $keysched, {@XMM[4]}            @ load round0 key
+#else
+       ldr     r12, [$key, #244]
+       eors    r12, #1
+       beq     0f
+
+       @ populate the key schedule
+       str     r12, [$key, #244]
+       mov     r4, $key                        @ pass key
+       mov     r5, $rounds                     @ pass # of rounds
+       add     r12, $key, #248                 @ pass key schedule
+       bl      _bsaes_key_convert
+       veor    @XMM[7],@XMM[7],@XMM[15]        @ fix up last round key
+       vstmia  r12, {@XMM[7]}                  @ save last round key
+
+.align 2
+0:     add     r12, $key, #248
+       vld1.8  {@XMM[0]}, [$ctr]               @ load counter
+       adrl    $ctr, .LREVM0SR                 @ borrow $ctr
+       vldmia  r12, {@XMM[4]}                  @ load round0 key
+       sub     sp, #0x10                       @ place for adjusted round0 key
+#endif
+
+       vmov.i32        @XMM[8],#1              @ compose 1<<96
+       veor            @XMM[9],@XMM[9],@XMM[9]
+       vrev32.8        @XMM[0],@XMM[0]
+       vext.8          @XMM[8],@XMM[9],@XMM[8],#4
+       vrev32.8        @XMM[4],@XMM[4]
+       vadd.u32        @XMM[9],@XMM[8],@XMM[8] @ compose 2<<96
+       vstmia  $keysched, {@XMM[4]}            @ save adjusted round0 key
+       b       .Lctr_enc_loop
+
+.align 4
+.Lctr_enc_loop:
+       vadd.u32        @XMM[10], @XMM[8], @XMM[9]      @ compose 3<<96
+       vadd.u32        @XMM[1], @XMM[0], @XMM[8]       @ +1
+       vadd.u32        @XMM[2], @XMM[0], @XMM[9]       @ +2
+       vadd.u32        @XMM[3], @XMM[0], @XMM[10]      @ +3
+       vadd.u32        @XMM[4], @XMM[1], @XMM[10]
+       vadd.u32        @XMM[5], @XMM[2], @XMM[10]
+       vadd.u32        @XMM[6], @XMM[3], @XMM[10]
+       vadd.u32        @XMM[7], @XMM[4], @XMM[10]
+       vadd.u32        @XMM[10], @XMM[5], @XMM[10]     @ next counter
+
+       @ Borrow prologue from _bsaes_encrypt8 to use the opportunity
+       @ to flip byte order in 32-bit counter
+
+       vldmia          $keysched, {@XMM[9]}            @ load round0 key
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, $keysched, #0x10            @ pass next round key
+#else
+       add             r4, $key, #`248+16`
+#endif
+       vldmia          $ctr, {@XMM[8]}                 @ .LREVM0SR
+       mov             r5, $rounds                     @ pass rounds
+       vstmia          $fp, {@XMM[10]}                 @ save next counter
+       sub             $const, $ctr, #.LREVM0SR-.LSR   @ pass constants
+
+       bl              _bsaes_encrypt8_alt
+
+       subs            $len, $len, #8
+       blo             .Lctr_enc_loop_done
+
+       vld1.8          {@XMM[8]-@XMM[9]}, [$inp]!      @ load input
+       vld1.8          {@XMM[10]-@XMM[11]}, [$inp]!
+       veor            @XMM[0], @XMM[8]
+       veor            @XMM[1], @XMM[9]
+       vld1.8          {@XMM[12]-@XMM[13]}, [$inp]!
+       veor            @XMM[4], @XMM[10]
+       veor            @XMM[6], @XMM[11]
+       vld1.8          {@XMM[14]-@XMM[15]}, [$inp]!
+       veor            @XMM[3], @XMM[12]
+       vst1.8          {@XMM[0]-@XMM[1]}, [$out]!      @ write output
+       veor            @XMM[7], @XMM[13]
+       veor            @XMM[2], @XMM[14]
+       vst1.8          {@XMM[4]}, [$out]!
+       veor            @XMM[5], @XMM[15]
+       vst1.8          {@XMM[6]}, [$out]!
+       vmov.i32        @XMM[8], #1                     @ compose 1<<96
+       vst1.8          {@XMM[3]}, [$out]!
+       veor            @XMM[9], @XMM[9], @XMM[9]
+       vst1.8          {@XMM[7]}, [$out]!
+       vext.8          @XMM[8], @XMM[9], @XMM[8], #4
+       vst1.8          {@XMM[2]}, [$out]!
+       vadd.u32        @XMM[9],@XMM[8],@XMM[8]         @ compose 2<<96
+       vst1.8          {@XMM[5]}, [$out]!
+       vldmia          $fp, {@XMM[0]}                  @ load counter
+
+       bne             .Lctr_enc_loop
+       b               .Lctr_enc_done
+
+.align 4
+.Lctr_enc_loop_done:
+       add             $len, $len, #8
+       vld1.8          {@XMM[8]}, [$inp]!      @ load input
+       veor            @XMM[0], @XMM[8]
+       vst1.8          {@XMM[0]}, [$out]!      @ write output
+       cmp             $len, #2
+       blo             .Lctr_enc_done
+       vld1.8          {@XMM[9]}, [$inp]!
+       veor            @XMM[1], @XMM[9]
+       vst1.8          {@XMM[1]}, [$out]!
+       beq             .Lctr_enc_done
+       vld1.8          {@XMM[10]}, [$inp]!
+       veor            @XMM[4], @XMM[10]
+       vst1.8          {@XMM[4]}, [$out]!
+       cmp             $len, #4
+       blo             .Lctr_enc_done
+       vld1.8          {@XMM[11]}, [$inp]!
+       veor            @XMM[6], @XMM[11]
+       vst1.8          {@XMM[6]}, [$out]!
+       beq             .Lctr_enc_done
+       vld1.8          {@XMM[12]}, [$inp]!
+       veor            @XMM[3], @XMM[12]
+       vst1.8          {@XMM[3]}, [$out]!
+       cmp             $len, #6
+       blo             .Lctr_enc_done
+       vld1.8          {@XMM[13]}, [$inp]!
+       veor            @XMM[7], @XMM[13]
+       vst1.8          {@XMM[7]}, [$out]!
+       beq             .Lctr_enc_done
+       vld1.8          {@XMM[14]}, [$inp]
+       veor            @XMM[2], @XMM[14]
+       vst1.8          {@XMM[2]}, [$out]!
+
+.Lctr_enc_done:
+       vmov.i32        q0, #0
+       vmov.i32        q1, #0
+#ifndef        BSAES_ASM_EXTENDED_KEY
+.Lctr_enc_bzero:                       @ wipe key schedule [if any]
+       vstmia          $keysched!, {q0-q1}
+       cmp             $keysched, $fp
+       bne             .Lctr_enc_bzero
+#else
+       vstmia          $keysched, {q0-q1}
+#endif
+
+       mov     sp, $fp
+       add     sp, #0x10               @ add sp,$fp,#0x10 is no good for thumb
+       VFP_ABI_POP
+       ldmia   sp!, {r4-r10, pc}       @ return
+
+.align 4
+.Lctr_enc_short:
+       ldr     ip, [sp]                @ ctr pointer is passed on stack
+       stmdb   sp!, {r4-r8, lr}
+
+       mov     r4, $inp                @ copy arguments
+       mov     r5, $out
+       mov     r6, $len
+       mov     r7, $key
+       ldr     r8, [ip, #12]           @ load counter LSW
+       vld1.8  {@XMM[1]}, [ip]         @ load whole counter value
+#ifdef __ARMEL__
+       rev     r8, r8
+#endif
+       sub     sp, sp, #0x10
+       vst1.8  {@XMM[1]}, [sp,:64]     @ copy counter value
+       sub     sp, sp, #0x10
+
+.Lctr_enc_short_loop:
+       add     r0, sp, #0x10           @ input counter value
+       mov     r1, sp                  @ output on the stack
+       mov     r2, r7                  @ key
+
+       bl      AES_encrypt
+
+       vld1.8  {@XMM[0]}, [r4]!        @ load input
+       vld1.8  {@XMM[1]}, [sp,:64]     @ load encrypted counter
+       add     r8, r8, #1
+#ifdef __ARMEL__
+       rev     r0, r8
+       str     r0, [sp, #0x1c]         @ next counter value
+#else
+       str     r8, [sp, #0x1c]         @ next counter value
+#endif
+       veor    @XMM[0],@XMM[0],@XMM[1]
+       vst1.8  {@XMM[0]}, [r5]!        @ store output
+       subs    r6, r6, #1
+       bne     .Lctr_enc_short_loop
+
+       vmov.i32        q0, #0
+       vmov.i32        q1, #0
+       vstmia          sp!, {q0-q1}
+
+       ldmia   sp!, {r4-r8, pc}
+.size  bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
+___
+}
+{
+######################################################################
+# void bsaes_xts_[en|de]crypt(const char *inp,char *out,size_t len,
+#      const AES_KEY *key1, const AES_KEY *key2,
+#      const unsigned char iv[16]);
+#
+my ($inp,$out,$len,$key,$rounds,$magic,$fp)=(map("r$_",(7..10,1..3)));
+my $const="r6";                # returned by _bsaes_key_convert
+my $twmask=@XMM[5];
+my @T=@XMM[6..7];
+
+$code.=<<___;
+.globl bsaes_xts_encrypt
+.type  bsaes_xts_encrypt,%function
+.align 4
+bsaes_xts_encrypt:
+       mov     ip, sp
+       stmdb   sp!, {r4-r10, lr}               @ 0x20
+       VFP_ABI_PUSH
+       mov     r6, sp                          @ future $fp
+
+       mov     $inp, r0
+       mov     $out, r1
+       mov     $len, r2
+       mov     $key, r3
+
+       sub     r0, sp, #0x10                   @ 0x10
+       bic     r0, #0xf                        @ align at 16 bytes
+       mov     sp, r0
+
+#ifdef XTS_CHAIN_TWEAK
+       ldr     r0, [ip]                        @ pointer to input tweak
+#else
+       @ generate initial tweak
+       ldr     r0, [ip, #4]                    @ iv[]
+       mov     r1, sp
+       ldr     r2, [ip, #0]                    @ key2
+       bl      AES_encrypt
+       mov     r0,sp                           @ pointer to initial tweak
+#endif
+
+       ldr     $rounds, [$key, #240]           @ get # of rounds
+       mov     $fp, r6
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       @ allocate the key schedule on the stack
+       sub     r12, sp, $rounds, lsl#7         @ 128 bytes per inner round key
+       @ add   r12, #`128-32`                  @ size of bit-sliced key schedule
+       sub     r12, #`32+16`                   @ place for tweak[9]
+
+       @ populate the key schedule
+       mov     r4, $key                        @ pass key
+       mov     r5, $rounds                     @ pass # of rounds
+       mov     sp, r12
+       add     r12, #0x90                      @ pass key schedule
+       bl      _bsaes_key_convert
+       veor    @XMM[7], @XMM[7], @XMM[15]      @ fix up last round key
+       vstmia  r12, {@XMM[7]}                  @ save last round key
+#else
+       ldr     r12, [$key, #244]
+       eors    r12, #1
+       beq     0f
+
+       str     r12, [$key, #244]
+       mov     r4, $key                        @ pass key
+       mov     r5, $rounds                     @ pass # of rounds
+       add     r12, $key, #248                 @ pass key schedule
+       bl      _bsaes_key_convert
+       veor    @XMM[7], @XMM[7], @XMM[15]      @ fix up last round key
+       vstmia  r12, {@XMM[7]}
+
+.align 2
+0:     sub     sp, #0x90                       @ place for tweak[9]
+#endif
+
+       vld1.8  {@XMM[8]}, [r0]                 @ initial tweak
+       adr     $magic, .Lxts_magic
+
+       subs    $len, #0x80
+       blo     .Lxts_enc_short
+       b       .Lxts_enc_loop
+
+.align 4
+.Lxts_enc_loop:
+       vldmia          $magic, {$twmask}       @ load XTS magic
+       vshr.s64        @T[0], @XMM[8], #63
+       mov             r0, sp
+       vand            @T[0], @T[0], $twmask
+___
+for($i=9;$i<16;$i++) {
+$code.=<<___;
+       vadd.u64        @XMM[$i], @XMM[$i-1], @XMM[$i-1]
+       vst1.64         {@XMM[$i-1]}, [r0,:128]!
+       vswp            `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
+       vshr.s64        @T[1], @XMM[$i], #63
+       veor            @XMM[$i], @XMM[$i], @T[0]
+       vand            @T[1], @T[1], $twmask
+___
+       @T=reverse(@T);
+
+$code.=<<___ if ($i>=10);
+       vld1.8          {@XMM[$i-10]}, [$inp]!
+___
+$code.=<<___ if ($i>=11);
+       veor            @XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
+___
+}
+$code.=<<___;
+       vadd.u64        @XMM[8], @XMM[15], @XMM[15]
+       vst1.64         {@XMM[15]}, [r0,:128]!
+       vswp            `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
+       veor            @XMM[8], @XMM[8], @T[0]
+       vst1.64         {@XMM[8]}, [r0,:128]            @ next round tweak
+
+       vld1.8          {@XMM[6]-@XMM[7]}, [$inp]!
+       veor            @XMM[5], @XMM[5], @XMM[13]
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, $key, #248                  @ pass key schedule
+#endif
+       veor            @XMM[6], @XMM[6], @XMM[14]
+       mov             r5, $rounds                     @ pass rounds
+       veor            @XMM[7], @XMM[7], @XMM[15]
+       mov             r0, sp
+
+       bl              _bsaes_encrypt8
+
+       vld1.64         {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+       vld1.64         {@XMM[10]-@XMM[11]}, [r0,:128]!
+       veor            @XMM[0], @XMM[0], @XMM[ 8]
+       vld1.64         {@XMM[12]-@XMM[13]}, [r0,:128]!
+       veor            @XMM[1], @XMM[1], @XMM[ 9]
+       veor            @XMM[8], @XMM[4], @XMM[10]
+       vst1.8          {@XMM[0]-@XMM[1]}, [$out]!
+       veor            @XMM[9], @XMM[6], @XMM[11]
+       vld1.64         {@XMM[14]-@XMM[15]}, [r0,:128]!
+       veor            @XMM[10], @XMM[3], @XMM[12]
+       vst1.8          {@XMM[8]-@XMM[9]}, [$out]!
+       veor            @XMM[11], @XMM[7], @XMM[13]
+       veor            @XMM[12], @XMM[2], @XMM[14]
+       vst1.8          {@XMM[10]-@XMM[11]}, [$out]!
+       veor            @XMM[13], @XMM[5], @XMM[15]
+       vst1.8          {@XMM[12]-@XMM[13]}, [$out]!
+
+       vld1.64         {@XMM[8]}, [r0,:128]            @ next round tweak
+
+       subs            $len, #0x80
+       bpl             .Lxts_enc_loop
+
+.Lxts_enc_short:
+       adds            $len, #0x70
+       bmi             .Lxts_enc_done
+
+       vldmia          $magic, {$twmask}       @ load XTS magic
+       vshr.s64        @T[0], @XMM[8], #63
+       mov             r0, sp
+       vand            @T[0], @T[0], $twmask
+___
+for($i=9;$i<16;$i++) {
+$code.=<<___;
+       vadd.u64        @XMM[$i], @XMM[$i-1], @XMM[$i-1]
+       vst1.64         {@XMM[$i-1]}, [r0,:128]!
+       vswp            `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
+       vshr.s64        @T[1], @XMM[$i], #63
+       veor            @XMM[$i], @XMM[$i], @T[0]
+       vand            @T[1], @T[1], $twmask
+___
+       @T=reverse(@T);
+
+$code.=<<___ if ($i>=10);
+       vld1.8          {@XMM[$i-10]}, [$inp]!
+       subs            $len, #0x10
+       bmi             .Lxts_enc_`$i-9`
+___
+$code.=<<___ if ($i>=11);
+       veor            @XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
+___
+}
+$code.=<<___;
+       sub             $len, #0x10
+       vst1.64         {@XMM[15]}, [r0,:128]           @ next round tweak
+
+       vld1.8          {@XMM[6]}, [$inp]!
+       veor            @XMM[5], @XMM[5], @XMM[13]
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, $key, #248                  @ pass key schedule
+#endif
+       veor            @XMM[6], @XMM[6], @XMM[14]
+       mov             r5, $rounds                     @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_encrypt8
+
+       vld1.64         {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+       vld1.64         {@XMM[10]-@XMM[11]}, [r0,:128]!
+       veor            @XMM[0], @XMM[0], @XMM[ 8]
+       vld1.64         {@XMM[12]-@XMM[13]}, [r0,:128]!
+       veor            @XMM[1], @XMM[1], @XMM[ 9]
+       veor            @XMM[8], @XMM[4], @XMM[10]
+       vst1.8          {@XMM[0]-@XMM[1]}, [$out]!
+       veor            @XMM[9], @XMM[6], @XMM[11]
+       vld1.64         {@XMM[14]}, [r0,:128]!
+       veor            @XMM[10], @XMM[3], @XMM[12]
+       vst1.8          {@XMM[8]-@XMM[9]}, [$out]!
+       veor            @XMM[11], @XMM[7], @XMM[13]
+       veor            @XMM[12], @XMM[2], @XMM[14]
+       vst1.8          {@XMM[10]-@XMM[11]}, [$out]!
+       vst1.8          {@XMM[12]}, [$out]!
+
+       vld1.64         {@XMM[8]}, [r0,:128]            @ next round tweak
+       b               .Lxts_enc_done
+.align 4
+.Lxts_enc_6:
+       vst1.64         {@XMM[14]}, [r0,:128]           @ next round tweak
+
+       veor            @XMM[4], @XMM[4], @XMM[12]
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, $key, #248                  @ pass key schedule
+#endif
+       veor            @XMM[5], @XMM[5], @XMM[13]
+       mov             r5, $rounds                     @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_encrypt8
+
+       vld1.64         {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+       vld1.64         {@XMM[10]-@XMM[11]}, [r0,:128]!
+       veor            @XMM[0], @XMM[0], @XMM[ 8]
+       vld1.64         {@XMM[12]-@XMM[13]}, [r0,:128]!
+       veor            @XMM[1], @XMM[1], @XMM[ 9]
+       veor            @XMM[8], @XMM[4], @XMM[10]
+       vst1.8          {@XMM[0]-@XMM[1]}, [$out]!
+       veor            @XMM[9], @XMM[6], @XMM[11]
+       veor            @XMM[10], @XMM[3], @XMM[12]
+       vst1.8          {@XMM[8]-@XMM[9]}, [$out]!
+       veor            @XMM[11], @XMM[7], @XMM[13]
+       vst1.8          {@XMM[10]-@XMM[11]}, [$out]!
+
+       vld1.64         {@XMM[8]}, [r0,:128]            @ next round tweak
+       b               .Lxts_enc_done
+
+@ put this in range for both ARM and Thumb mode adr instructions
+.align 5
+.Lxts_magic:
+       .quad   1, 0x87
+
+.align 5
+.Lxts_enc_5:
+       vst1.64         {@XMM[13]}, [r0,:128]           @ next round tweak
+
+       veor            @XMM[3], @XMM[3], @XMM[11]
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, $key, #248                  @ pass key schedule
+#endif
+       veor            @XMM[4], @XMM[4], @XMM[12]
+       mov             r5, $rounds                     @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_encrypt8
+
+       vld1.64         {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+       vld1.64         {@XMM[10]-@XMM[11]}, [r0,:128]!
+       veor            @XMM[0], @XMM[0], @XMM[ 8]
+       vld1.64         {@XMM[12]}, [r0,:128]!
+       veor            @XMM[1], @XMM[1], @XMM[ 9]
+       veor            @XMM[8], @XMM[4], @XMM[10]
+       vst1.8          {@XMM[0]-@XMM[1]}, [$out]!
+       veor            @XMM[9], @XMM[6], @XMM[11]
+       veor            @XMM[10], @XMM[3], @XMM[12]
+       vst1.8          {@XMM[8]-@XMM[9]}, [$out]!
+       vst1.8          {@XMM[10]}, [$out]!
+
+       vld1.64         {@XMM[8]}, [r0,:128]            @ next round tweak
+       b               .Lxts_enc_done
+.align 4
+.Lxts_enc_4:
+       vst1.64         {@XMM[12]}, [r0,:128]           @ next round tweak
+
+       veor            @XMM[2], @XMM[2], @XMM[10]
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, $key, #248                  @ pass key schedule
+#endif
+       veor            @XMM[3], @XMM[3], @XMM[11]
+       mov             r5, $rounds                     @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_encrypt8
+
+       vld1.64         {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+       vld1.64         {@XMM[10]-@XMM[11]}, [r0,:128]!
+       veor            @XMM[0], @XMM[0], @XMM[ 8]
+       veor            @XMM[1], @XMM[1], @XMM[ 9]
+       veor            @XMM[8], @XMM[4], @XMM[10]
+       vst1.8          {@XMM[0]-@XMM[1]}, [$out]!
+       veor            @XMM[9], @XMM[6], @XMM[11]
+       vst1.8          {@XMM[8]-@XMM[9]}, [$out]!
+
+       vld1.64         {@XMM[8]}, [r0,:128]            @ next round tweak
+       b               .Lxts_enc_done
+.align 4
+.Lxts_enc_3:
+       vst1.64         {@XMM[11]}, [r0,:128]           @ next round tweak
+
+       veor            @XMM[1], @XMM[1], @XMM[9]
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, $key, #248                  @ pass key schedule
+#endif
+       veor            @XMM[2], @XMM[2], @XMM[10]
+       mov             r5, $rounds                     @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_encrypt8
+
+       vld1.64         {@XMM[8]-@XMM[9]}, [r0,:128]!
+       vld1.64         {@XMM[10]}, [r0,:128]!
+       veor            @XMM[0], @XMM[0], @XMM[ 8]
+       veor            @XMM[1], @XMM[1], @XMM[ 9]
+       veor            @XMM[8], @XMM[4], @XMM[10]
+       vst1.8          {@XMM[0]-@XMM[1]}, [$out]!
+       vst1.8          {@XMM[8]}, [$out]!
+
+       vld1.64         {@XMM[8]}, [r0,:128]            @ next round tweak
+       b               .Lxts_enc_done
+.align 4
+.Lxts_enc_2:
+       vst1.64         {@XMM[10]}, [r0,:128]           @ next round tweak
+
+       veor            @XMM[0], @XMM[0], @XMM[8]
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, $key, #248                  @ pass key schedule
+#endif
+       veor            @XMM[1], @XMM[1], @XMM[9]
+       mov             r5, $rounds                     @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_encrypt8
+
+       vld1.64         {@XMM[8]-@XMM[9]}, [r0,:128]!
+       veor            @XMM[0], @XMM[0], @XMM[ 8]
+       veor            @XMM[1], @XMM[1], @XMM[ 9]
+       vst1.8          {@XMM[0]-@XMM[1]}, [$out]!
+
+       vld1.64         {@XMM[8]}, [r0,:128]            @ next round tweak
+       b               .Lxts_enc_done
+.align 4
+.Lxts_enc_1:
+       mov             r0, sp
+       veor            @XMM[0], @XMM[8]
+       mov             r1, sp
+       vst1.8          {@XMM[0]}, [sp,:128]
+       mov             r2, $key
+       mov             r4, $fp                         @ preserve fp
+
+       bl              AES_encrypt
+
+       vld1.8          {@XMM[0]}, [sp,:128]
+       veor            @XMM[0], @XMM[0], @XMM[8]
+       vst1.8          {@XMM[0]}, [$out]!
+       mov             $fp, r4
+
+       vmov            @XMM[8], @XMM[9]                @ next round tweak
+
+.Lxts_enc_done:
+#ifndef        XTS_CHAIN_TWEAK
+       adds            $len, #0x10
+       beq             .Lxts_enc_ret
+       sub             r6, $out, #0x10
+
+.Lxts_enc_steal:
+       ldrb            r0, [$inp], #1
+       ldrb            r1, [$out, #-0x10]
+       strb            r0, [$out, #-0x10]
+       strb            r1, [$out], #1
+
+       subs            $len, #1
+       bhi             .Lxts_enc_steal
+
+       vld1.8          {@XMM[0]}, [r6]
+       mov             r0, sp
+       veor            @XMM[0], @XMM[0], @XMM[8]
+       mov             r1, sp
+       vst1.8          {@XMM[0]}, [sp,:128]
+       mov             r2, $key
+       mov             r4, $fp                 @ preserve fp
+
+       bl              AES_encrypt
+
+       vld1.8          {@XMM[0]}, [sp,:128]
+       veor            @XMM[0], @XMM[0], @XMM[8]
+       vst1.8          {@XMM[0]}, [r6]
+       mov             $fp, r4
+#endif
+
+.Lxts_enc_ret:
+       bic             r0, $fp, #0xf
+       vmov.i32        q0, #0
+       vmov.i32        q1, #0
+#ifdef XTS_CHAIN_TWEAK
+       ldr             r1, [$fp, #0x20+VFP_ABI_FRAME]  @ chain tweak
+#endif
+.Lxts_enc_bzero:                               @ wipe key schedule [if any]
+       vstmia          sp!, {q0-q1}
+       cmp             sp, r0
+       bne             .Lxts_enc_bzero
+
+       mov             sp, $fp
+#ifdef XTS_CHAIN_TWEAK
+       vst1.8          {@XMM[8]}, [r1]
+#endif
+       VFP_ABI_POP
+       ldmia           sp!, {r4-r10, pc}       @ return
+
+.size  bsaes_xts_encrypt,.-bsaes_xts_encrypt
+
+.globl bsaes_xts_decrypt
+.type  bsaes_xts_decrypt,%function
+.align 4
+bsaes_xts_decrypt:
+       mov     ip, sp
+       stmdb   sp!, {r4-r10, lr}               @ 0x20
+       VFP_ABI_PUSH
+       mov     r6, sp                          @ future $fp
+
+       mov     $inp, r0
+       mov     $out, r1
+       mov     $len, r2
+       mov     $key, r3
+
+       sub     r0, sp, #0x10                   @ 0x10
+       bic     r0, #0xf                        @ align at 16 bytes
+       mov     sp, r0
+
+#ifdef XTS_CHAIN_TWEAK
+       ldr     r0, [ip]                        @ pointer to input tweak
+#else
+       @ generate initial tweak
+       ldr     r0, [ip, #4]                    @ iv[]
+       mov     r1, sp
+       ldr     r2, [ip, #0]                    @ key2
+       bl      AES_encrypt
+       mov     r0, sp                          @ pointer to initial tweak
+#endif
+
+       ldr     $rounds, [$key, #240]           @ get # of rounds
+       mov     $fp, r6
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       @ allocate the key schedule on the stack
+       sub     r12, sp, $rounds, lsl#7         @ 128 bytes per inner round key
+       @ add   r12, #`128-32`                  @ size of bit-sliced key schedule
+       sub     r12, #`32+16`                   @ place for tweak[9]
+
+       @ populate the key schedule
+       mov     r4, $key                        @ pass key
+       mov     r5, $rounds                     @ pass # of rounds
+       mov     sp, r12
+       add     r12, #0x90                      @ pass key schedule
+       bl      _bsaes_key_convert
+       add     r4, sp, #0x90
+       vldmia  r4, {@XMM[6]}
+       vstmia  r12,  {@XMM[15]}                @ save last round key
+       veor    @XMM[7], @XMM[7], @XMM[6]       @ fix up round 0 key
+       vstmia  r4, {@XMM[7]}
+#else
+       ldr     r12, [$key, #244]
+       eors    r12, #1
+       beq     0f
+
+       str     r12, [$key, #244]
+       mov     r4, $key                        @ pass key
+       mov     r5, $rounds                     @ pass # of rounds
+       add     r12, $key, #248                 @ pass key schedule
+       bl      _bsaes_key_convert
+       add     r4, $key, #248
+       vldmia  r4, {@XMM[6]}
+       vstmia  r12,  {@XMM[15]}                @ save last round key
+       veor    @XMM[7], @XMM[7], @XMM[6]       @ fix up round 0 key
+       vstmia  r4, {@XMM[7]}
+
+.align 2
+0:     sub     sp, #0x90                       @ place for tweak[9]
+#endif
+       vld1.8  {@XMM[8]}, [r0]                 @ initial tweak
+       adr     $magic, .Lxts_magic
+
+       tst     $len, #0xf                      @ if not multiple of 16
+       it      ne                              @ Thumb2 thing, sanity check in ARM
+       subne   $len, #0x10                     @ subtract another 16 bytes
+       subs    $len, #0x80
+
+       blo     .Lxts_dec_short
+       b       .Lxts_dec_loop
+
+.align 4
+.Lxts_dec_loop:
+       vldmia          $magic, {$twmask}       @ load XTS magic
+       vshr.s64        @T[0], @XMM[8], #63
+       mov             r0, sp
+       vand            @T[0], @T[0], $twmask
+___
+for($i=9;$i<16;$i++) {
+$code.=<<___;
+       vadd.u64        @XMM[$i], @XMM[$i-1], @XMM[$i-1]
+       vst1.64         {@XMM[$i-1]}, [r0,:128]!
+       vswp            `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
+       vshr.s64        @T[1], @XMM[$i], #63
+       veor            @XMM[$i], @XMM[$i], @T[0]
+       vand            @T[1], @T[1], $twmask
+___
+       @T=reverse(@T);
+
+$code.=<<___ if ($i>=10);
+       vld1.8          {@XMM[$i-10]}, [$inp]!
+___
+$code.=<<___ if ($i>=11);
+       veor            @XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
+___
+}
+$code.=<<___;
+       vadd.u64        @XMM[8], @XMM[15], @XMM[15]
+       vst1.64         {@XMM[15]}, [r0,:128]!
+       vswp            `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
+       veor            @XMM[8], @XMM[8], @T[0]
+       vst1.64         {@XMM[8]}, [r0,:128]            @ next round tweak
+
+       vld1.8          {@XMM[6]-@XMM[7]}, [$inp]!
+       veor            @XMM[5], @XMM[5], @XMM[13]
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, $key, #248                  @ pass key schedule
+#endif
+       veor            @XMM[6], @XMM[6], @XMM[14]
+       mov             r5, $rounds                     @ pass rounds
+       veor            @XMM[7], @XMM[7], @XMM[15]
+       mov             r0, sp
+
+       bl              _bsaes_decrypt8
+
+       vld1.64         {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+       vld1.64         {@XMM[10]-@XMM[11]}, [r0,:128]!
+       veor            @XMM[0], @XMM[0], @XMM[ 8]
+       vld1.64         {@XMM[12]-@XMM[13]}, [r0,:128]!
+       veor            @XMM[1], @XMM[1], @XMM[ 9]
+       veor            @XMM[8], @XMM[6], @XMM[10]
+       vst1.8          {@XMM[0]-@XMM[1]}, [$out]!
+       veor            @XMM[9], @XMM[4], @XMM[11]
+       vld1.64         {@XMM[14]-@XMM[15]}, [r0,:128]!
+       veor            @XMM[10], @XMM[2], @XMM[12]
+       vst1.8          {@XMM[8]-@XMM[9]}, [$out]!
+       veor            @XMM[11], @XMM[7], @XMM[13]
+       veor            @XMM[12], @XMM[3], @XMM[14]
+       vst1.8          {@XMM[10]-@XMM[11]}, [$out]!
+       veor            @XMM[13], @XMM[5], @XMM[15]
+       vst1.8          {@XMM[12]-@XMM[13]}, [$out]!
+
+       vld1.64         {@XMM[8]}, [r0,:128]            @ next round tweak
+
+       subs            $len, #0x80
+       bpl             .Lxts_dec_loop
+
+.Lxts_dec_short:
+       adds            $len, #0x70
+       bmi             .Lxts_dec_done
+
+       vldmia          $magic, {$twmask}       @ load XTS magic
+       vshr.s64        @T[0], @XMM[8], #63
+       mov             r0, sp
+       vand            @T[0], @T[0], $twmask
+___
+for($i=9;$i<16;$i++) {
+$code.=<<___;
+       vadd.u64        @XMM[$i], @XMM[$i-1], @XMM[$i-1]
+       vst1.64         {@XMM[$i-1]}, [r0,:128]!
+       vswp            `&Dhi("@T[0]")`,`&Dlo("@T[0]")`
+       vshr.s64        @T[1], @XMM[$i], #63
+       veor            @XMM[$i], @XMM[$i], @T[0]
+       vand            @T[1], @T[1], $twmask
+___
+       @T=reverse(@T);
+
+$code.=<<___ if ($i>=10);
+       vld1.8          {@XMM[$i-10]}, [$inp]!
+       subs            $len, #0x10
+       bmi             .Lxts_dec_`$i-9`
+___
+$code.=<<___ if ($i>=11);
+       veor            @XMM[$i-11], @XMM[$i-11], @XMM[$i-3]
+___
+}
+$code.=<<___;
+       sub             $len, #0x10
+       vst1.64         {@XMM[15]}, [r0,:128]           @ next round tweak
+
+       vld1.8          {@XMM[6]}, [$inp]!
+       veor            @XMM[5], @XMM[5], @XMM[13]
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, $key, #248                  @ pass key schedule
+#endif
+       veor            @XMM[6], @XMM[6], @XMM[14]
+       mov             r5, $rounds                     @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_decrypt8
+
+       vld1.64         {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+       vld1.64         {@XMM[10]-@XMM[11]}, [r0,:128]!
+       veor            @XMM[0], @XMM[0], @XMM[ 8]
+       vld1.64         {@XMM[12]-@XMM[13]}, [r0,:128]!
+       veor            @XMM[1], @XMM[1], @XMM[ 9]
+       veor            @XMM[8], @XMM[6], @XMM[10]
+       vst1.8          {@XMM[0]-@XMM[1]}, [$out]!
+       veor            @XMM[9], @XMM[4], @XMM[11]
+       vld1.64         {@XMM[14]}, [r0,:128]!
+       veor            @XMM[10], @XMM[2], @XMM[12]
+       vst1.8          {@XMM[8]-@XMM[9]}, [$out]!
+       veor            @XMM[11], @XMM[7], @XMM[13]
+       veor            @XMM[12], @XMM[3], @XMM[14]
+       vst1.8          {@XMM[10]-@XMM[11]}, [$out]!
+       vst1.8          {@XMM[12]}, [$out]!
+
+       vld1.64         {@XMM[8]}, [r0,:128]            @ next round tweak
+       b               .Lxts_dec_done
+.align 4
+.Lxts_dec_6:
+       vst1.64         {@XMM[14]}, [r0,:128]           @ next round tweak
+
+       veor            @XMM[4], @XMM[4], @XMM[12]
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, $key, #248                  @ pass key schedule
+#endif
+       veor            @XMM[5], @XMM[5], @XMM[13]
+       mov             r5, $rounds                     @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_decrypt8
+
+       vld1.64         {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+       vld1.64         {@XMM[10]-@XMM[11]}, [r0,:128]!
+       veor            @XMM[0], @XMM[0], @XMM[ 8]
+       vld1.64         {@XMM[12]-@XMM[13]}, [r0,:128]!
+       veor            @XMM[1], @XMM[1], @XMM[ 9]
+       veor            @XMM[8], @XMM[6], @XMM[10]
+       vst1.8          {@XMM[0]-@XMM[1]}, [$out]!
+       veor            @XMM[9], @XMM[4], @XMM[11]
+       veor            @XMM[10], @XMM[2], @XMM[12]
+       vst1.8          {@XMM[8]-@XMM[9]}, [$out]!
+       veor            @XMM[11], @XMM[7], @XMM[13]
+       vst1.8          {@XMM[10]-@XMM[11]}, [$out]!
+
+       vld1.64         {@XMM[8]}, [r0,:128]            @ next round tweak
+       b               .Lxts_dec_done
+.align 4
+.Lxts_dec_5:
+       vst1.64         {@XMM[13]}, [r0,:128]           @ next round tweak
+
+       veor            @XMM[3], @XMM[3], @XMM[11]
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, $key, #248                  @ pass key schedule
+#endif
+       veor            @XMM[4], @XMM[4], @XMM[12]
+       mov             r5, $rounds                     @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_decrypt8
+
+       vld1.64         {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+       vld1.64         {@XMM[10]-@XMM[11]}, [r0,:128]!
+       veor            @XMM[0], @XMM[0], @XMM[ 8]
+       vld1.64         {@XMM[12]}, [r0,:128]!
+       veor            @XMM[1], @XMM[1], @XMM[ 9]
+       veor            @XMM[8], @XMM[6], @XMM[10]
+       vst1.8          {@XMM[0]-@XMM[1]}, [$out]!
+       veor            @XMM[9], @XMM[4], @XMM[11]
+       veor            @XMM[10], @XMM[2], @XMM[12]
+       vst1.8          {@XMM[8]-@XMM[9]}, [$out]!
+       vst1.8          {@XMM[10]}, [$out]!
+
+       vld1.64         {@XMM[8]}, [r0,:128]            @ next round tweak
+       b               .Lxts_dec_done
+.align 4
+.Lxts_dec_4:
+       vst1.64         {@XMM[12]}, [r0,:128]           @ next round tweak
+
+       veor            @XMM[2], @XMM[2], @XMM[10]
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, $key, #248                  @ pass key schedule
+#endif
+       veor            @XMM[3], @XMM[3], @XMM[11]
+       mov             r5, $rounds                     @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_decrypt8
+
+       vld1.64         {@XMM[ 8]-@XMM[ 9]}, [r0,:128]!
+       vld1.64         {@XMM[10]-@XMM[11]}, [r0,:128]!
+       veor            @XMM[0], @XMM[0], @XMM[ 8]
+       veor            @XMM[1], @XMM[1], @XMM[ 9]
+       veor            @XMM[8], @XMM[6], @XMM[10]
+       vst1.8          {@XMM[0]-@XMM[1]}, [$out]!
+       veor            @XMM[9], @XMM[4], @XMM[11]
+       vst1.8          {@XMM[8]-@XMM[9]}, [$out]!
+
+       vld1.64         {@XMM[8]}, [r0,:128]            @ next round tweak
+       b               .Lxts_dec_done
+.align 4
+.Lxts_dec_3:
+       vst1.64         {@XMM[11]}, [r0,:128]           @ next round tweak
+
+       veor            @XMM[1], @XMM[1], @XMM[9]
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, $key, #248                  @ pass key schedule
+#endif
+       veor            @XMM[2], @XMM[2], @XMM[10]
+       mov             r5, $rounds                     @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_decrypt8
+
+       vld1.64         {@XMM[8]-@XMM[9]}, [r0,:128]!
+       vld1.64         {@XMM[10]}, [r0,:128]!
+       veor            @XMM[0], @XMM[0], @XMM[ 8]
+       veor            @XMM[1], @XMM[1], @XMM[ 9]
+       veor            @XMM[8], @XMM[6], @XMM[10]
+       vst1.8          {@XMM[0]-@XMM[1]}, [$out]!
+       vst1.8          {@XMM[8]}, [$out]!
+
+       vld1.64         {@XMM[8]}, [r0,:128]            @ next round tweak
+       b               .Lxts_dec_done
+.align 4
+.Lxts_dec_2:
+       vst1.64         {@XMM[10]}, [r0,:128]           @ next round tweak
+
+       veor            @XMM[0], @XMM[0], @XMM[8]
+#ifndef        BSAES_ASM_EXTENDED_KEY
+       add             r4, sp, #0x90                   @ pass key schedule
+#else
+       add             r4, $key, #248                  @ pass key schedule
+#endif
+       veor            @XMM[1], @XMM[1], @XMM[9]
+       mov             r5, $rounds                     @ pass rounds
+       mov             r0, sp
+
+       bl              _bsaes_decrypt8
+
+       vld1.64         {@XMM[8]-@XMM[9]}, [r0,:128]!
+       veor            @XMM[0], @XMM[0], @XMM[ 8]
+       veor            @XMM[1], @XMM[1], @XMM[ 9]
+       vst1.8          {@XMM[0]-@XMM[1]}, [$out]!
+
+       vld1.64         {@XMM[8]}, [r0,:128]            @ next round tweak
+       b               .Lxts_dec_done
+.align 4
+.Lxts_dec_1:
+       mov             r0, sp
+       veor            @XMM[0], @XMM[8]
+       mov             r1, sp
+       vst1.8          {@XMM[0]}, [sp,:128]
+       mov             r2, $key
+       mov             r4, $fp                         @ preserve fp
+       mov             r5, $magic                      @ preserve magic
+
+       bl              AES_decrypt
+
+       vld1.8          {@XMM[0]}, [sp,:128]
+       veor            @XMM[0], @XMM[0], @XMM[8]
+       vst1.8          {@XMM[0]}, [$out]!
+       mov             $fp, r4
+       mov             $magic, r5
+
+       vmov            @XMM[8], @XMM[9]                @ next round tweak
+
+.Lxts_dec_done:
+#ifndef        XTS_CHAIN_TWEAK
+       adds            $len, #0x10
+       beq             .Lxts_dec_ret
+
+       @ calculate one round of extra tweak for the stolen ciphertext
+       vldmia          $magic, {$twmask}
+       vshr.s64        @XMM[6], @XMM[8], #63
+       vand            @XMM[6], @XMM[6], $twmask
+       vadd.u64        @XMM[9], @XMM[8], @XMM[8]
+       vswp            `&Dhi("@XMM[6]")`,`&Dlo("@XMM[6]")`
+       veor            @XMM[9], @XMM[9], @XMM[6]
+
+       @ perform the final decryption with the last tweak value
+       vld1.8          {@XMM[0]}, [$inp]!
+       mov             r0, sp
+       veor            @XMM[0], @XMM[0], @XMM[9]
+       mov             r1, sp
+       vst1.8          {@XMM[0]}, [sp,:128]
+       mov             r2, $key
+       mov             r4, $fp                 @ preserve fp
+
+       bl              AES_decrypt
+
+       vld1.8          {@XMM[0]}, [sp,:128]
+       veor            @XMM[0], @XMM[0], @XMM[9]
+       vst1.8          {@XMM[0]}, [$out]
+
+       mov             r6, $out
+.Lxts_dec_steal:
+       ldrb            r1, [$out]
+       ldrb            r0, [$inp], #1
+       strb            r1, [$out, #0x10]
+       strb            r0, [$out], #1
+
+       subs            $len, #1
+       bhi             .Lxts_dec_steal
+
+       vld1.8          {@XMM[0]}, [r6]
+       mov             r0, sp
+       veor            @XMM[0], @XMM[8]
+       mov             r1, sp
+       vst1.8          {@XMM[0]}, [sp,:128]
+       mov             r2, $key
+
+       bl              AES_decrypt
+
+       vld1.8          {@XMM[0]}, [sp,:128]
+       veor            @XMM[0], @XMM[0], @XMM[8]
+       vst1.8          {@XMM[0]}, [r6]
+       mov             $fp, r4
+#endif
+
+.Lxts_dec_ret:
+       bic             r0, $fp, #0xf
+       vmov.i32        q0, #0
+       vmov.i32        q1, #0
+#ifdef XTS_CHAIN_TWEAK
+       ldr             r1, [$fp, #0x20+VFP_ABI_FRAME]  @ chain tweak
+#endif
+.Lxts_dec_bzero:                               @ wipe key schedule [if any]
+       vstmia          sp!, {q0-q1}
+       cmp             sp, r0
+       bne             .Lxts_dec_bzero
+
+       mov             sp, $fp
+#ifdef XTS_CHAIN_TWEAK
+       vst1.8          {@XMM[8]}, [r1]
+#endif
+       VFP_ABI_POP
+       ldmia           sp!, {r4-r10, pc}       @ return
+
+.size  bsaes_xts_decrypt,.-bsaes_xts_decrypt
+___
+}
+$code.=<<___;
+#endif
+___
+
+$code =~ s/\`([^\`]*)\`/eval($1)/gem;
+
+open SELF,$0;
+while(<SELF>) {
+       next if (/^#!/);
+        last if (!s/^#/@/ and !/^$/);
+        print;
+}
+close SELF;
+
+print $code;
+
+close STDOUT;
index 59ceae8f3c959616851a21ba3f08ae18941146ca..a6395c0277152f74645b8fceb572abc9b1c5a2db 100644 (file)
@@ -24,6 +24,7 @@ generic-y += sembuf.h
 generic-y += serial.h
 generic-y += shmbuf.h
 generic-y += siginfo.h
+generic-y += simd.h
 generic-y += sizes.h
 generic-y += socket.h
 generic-y += sockios.h
index da1c77d39327963ab10e633aeb8809aac7da2dec..55ffc3b850f43e17b4337c83af16c1c0bdf81afc 100644 (file)
@@ -12,6 +12,7 @@
 #define __ASM_ARM_ATOMIC_H
 
 #include <linux/compiler.h>
+#include <linux/prefetch.h>
 #include <linux/types.h>
 #include <linux/irqflags.h>
 #include <asm/barrier.h>
@@ -41,6 +42,7 @@ static inline void atomic_add(int i, atomic_t *v)
        unsigned long tmp;
        int result;
 
+       prefetchw(&v->counter);
        __asm__ __volatile__("@ atomic_add\n"
 "1:    ldrex   %0, [%3]\n"
 "      add     %0, %0, %4\n"
@@ -79,6 +81,7 @@ static inline void atomic_sub(int i, atomic_t *v)
        unsigned long tmp;
        int result;
 
+       prefetchw(&v->counter);
        __asm__ __volatile__("@ atomic_sub\n"
 "1:    ldrex   %0, [%3]\n"
 "      sub     %0, %0, %4\n"
@@ -138,6 +141,7 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
 {
        unsigned long tmp, tmp2;
 
+       prefetchw(addr);
        __asm__ __volatile__("@ atomic_clear_mask\n"
 "1:    ldrex   %0, [%3]\n"
 "      bic     %0, %0, %4\n"
@@ -283,6 +287,7 @@ static inline void atomic64_set(atomic64_t *v, u64 i)
 {
        u64 tmp;
 
+       prefetchw(&v->counter);
        __asm__ __volatile__("@ atomic64_set\n"
 "1:    ldrexd  %0, %H0, [%2]\n"
 "      strexd  %0, %3, %H3, [%2]\n"
@@ -299,6 +304,7 @@ static inline void atomic64_add(u64 i, atomic64_t *v)
        u64 result;
        unsigned long tmp;
 
+       prefetchw(&v->counter);
        __asm__ __volatile__("@ atomic64_add\n"
 "1:    ldrexd  %0, %H0, [%3]\n"
 "      adds    %0, %0, %4\n"
@@ -339,6 +345,7 @@ static inline void atomic64_sub(u64 i, atomic64_t *v)
        u64 result;
        unsigned long tmp;
 
+       prefetchw(&v->counter);
        __asm__ __volatile__("@ atomic64_sub\n"
 "1:    ldrexd  %0, %H0, [%3]\n"
 "      subs    %0, %0, %4\n"
diff --git a/arch/arm/include/asm/bL_switcher.h b/arch/arm/include/asm/bL_switcher.h
new file mode 100644 (file)
index 0000000..1714800
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * arch/arm/include/asm/bL_switcher.h
+ *
+ * Created by:  Nicolas Pitre, April 2012
+ * Copyright:   (C) 2012-2013  Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef ASM_BL_SWITCHER_H
+#define ASM_BL_SWITCHER_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+typedef void (*bL_switch_completion_handler)(void *cookie);
+
+int bL_switch_request_cb(unsigned int cpu, unsigned int new_cluster_id,
+                        bL_switch_completion_handler completer,
+                        void *completer_cookie);
+static inline int bL_switch_request(unsigned int cpu, unsigned int new_cluster_id)
+{
+       return bL_switch_request_cb(cpu, new_cluster_id, NULL, NULL);
+}
+
+/*
+ * Register here to be notified about runtime enabling/disabling of
+ * the switcher.
+ *
+ * The notifier chain is called with the switcher activation lock held:
+ * the switcher will not be enabled or disabled during callbacks.
+ * Callbacks must not call bL_switcher_{get,put}_enabled().
+ */
+#define BL_NOTIFY_PRE_ENABLE   0
+#define BL_NOTIFY_POST_ENABLE  1
+#define BL_NOTIFY_PRE_DISABLE  2
+#define BL_NOTIFY_POST_DISABLE 3
+
+#ifdef CONFIG_BL_SWITCHER
+
+int bL_switcher_register_notifier(struct notifier_block *nb);
+int bL_switcher_unregister_notifier(struct notifier_block *nb);
+
+/*
+ * Use these functions to temporarily prevent enabling/disabling of
+ * the switcher.
+ * bL_switcher_get_enabled() returns true if the switcher is currently
+ * enabled.  Each call to bL_switcher_get_enabled() must be followed
+ * by a call to bL_switcher_put_enabled().  These functions are not
+ * recursive.
+ */
+bool bL_switcher_get_enabled(void);
+void bL_switcher_put_enabled(void);
+
+int bL_switcher_trace_trigger(void);
+int bL_switcher_get_logical_index(u32 mpidr);
+
+#else
+static inline int bL_switcher_register_notifier(struct notifier_block *nb)
+{
+       return 0;
+}
+
+static inline int bL_switcher_unregister_notifier(struct notifier_block *nb)
+{
+       return 0;
+}
+
+static inline bool bL_switcher_get_enabled(void) { return false; }
+static inline void bL_switcher_put_enabled(void) { }
+static inline int bL_switcher_trace_trigger(void) { return 0; }
+static inline int bL_switcher_get_logical_index(u32 mpidr) { return -EUNATCH; }
+#endif /* CONFIG_BL_SWITCHER */
+
+#endif
index 4f009c10540dff2a2e7efd08b0671c2369547b90..df2fbba7efc80d57074a6053704a9c70119aae03 100644 (file)
@@ -223,6 +223,42 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
        return ret;
 }
 
+static inline unsigned long long __cmpxchg64(unsigned long long *ptr,
+                                            unsigned long long old,
+                                            unsigned long long new)
+{
+       unsigned long long oldval;
+       unsigned long res;
+
+       __asm__ __volatile__(
+"1:    ldrexd          %1, %H1, [%3]\n"
+"      teq             %1, %4\n"
+"      teqeq           %H1, %H4\n"
+"      bne             2f\n"
+"      strexd          %0, %5, %H5, [%3]\n"
+"      teq             %0, #0\n"
+"      bne             1b\n"
+"2:"
+       : "=&r" (res), "=&r" (oldval), "+Qo" (*ptr)
+       : "r" (ptr), "r" (old), "r" (new)
+       : "cc");
+
+       return oldval;
+}
+
+static inline unsigned long long __cmpxchg64_mb(unsigned long long *ptr,
+                                               unsigned long long old,
+                                               unsigned long long new)
+{
+       unsigned long long ret;
+
+       smp_mb();
+       ret = __cmpxchg64(ptr, old, new);
+       smp_mb();
+
+       return ret;
+}
+
 #define cmpxchg_local(ptr,o,n)                                         \
        ((__typeof__(*(ptr)))__cmpxchg_local((ptr),                     \
                                       (unsigned long)(o),              \
@@ -230,18 +266,16 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
                                       sizeof(*(ptr))))
 
 #define cmpxchg64(ptr, o, n)                                           \
-       ((__typeof__(*(ptr)))atomic64_cmpxchg(container_of((ptr),       \
-                                               atomic64_t,             \
-                                               counter),               \
-                                             (unsigned long long)(o),  \
-                                             (unsigned long long)(n)))
-
-#define cmpxchg64_local(ptr, o, n)                                     \
-       ((__typeof__(*(ptr)))local64_cmpxchg(container_of((ptr),        \
-                                               local64_t,              \
-                                               a),                     \
-                                            (unsigned long long)(o),   \
-                                            (unsigned long long)(n)))
+       ((__typeof__(*(ptr)))__cmpxchg64_mb((ptr),                      \
+                                       (unsigned long long)(o),        \
+                                       (unsigned long long)(n)))
+
+#define cmpxchg64_relaxed(ptr, o, n)                                   \
+       ((__typeof__(*(ptr)))__cmpxchg64((ptr),                         \
+                                       (unsigned long long)(o),        \
+                                       (unsigned long long)(n)))
+
+#define cmpxchg64_local(ptr, o, n)     cmpxchg64_relaxed((ptr), (o), (n))
 
 #endif /* __LINUX_ARM_ARCH__ >= 6 */
 
index 9672e978d50df67d94c3dd86d23f3bcdd187c54d..acdde76b39bbae3064034fff78b9dd2b95bbd39c 100644 (file)
@@ -10,6 +10,7 @@
 #define CPUID_TLBTYPE  3
 #define CPUID_MPUIR    4
 #define CPUID_MPIDR    5
+#define CPUID_REVIDR   6
 
 #ifdef CONFIG_CPU_V7M
 #define CPUID_EXT_PFR0 0x40
index 5b579b951503e51a436683d6fb0be964d983bf67..863cd84eb1a24955e9af8253dcfa8f0b710c95ae 100644 (file)
@@ -64,6 +64,7 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
 {
        return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
 }
+
 #else
 static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)
 {
@@ -86,6 +87,13 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
 }
 #endif
 
+/* The ARM override for dma_max_pfn() */
+static inline unsigned long dma_max_pfn(struct device *dev)
+{
+       return PHYS_PFN_OFFSET + dma_to_pfn(dev, *dev->dma_mask);
+}
+#define dma_max_pfn(dev) dma_max_pfn(dev)
+
 /*
  * DMA errors are defined by all-bits-set in the DMA address.
  */
index 2740c2a2df639361617f6fe484ead14f8625eaf2..3d7351c844aac0ae2392d441796ce9904dcaf717 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/threads.h>
 #include <asm/irq.h>
 
-#define NR_IPI 6
+#define NR_IPI 7
 
 typedef struct {
        unsigned int __softirq_pending;
index 402a2bc6aa687b94b09af6efa039c58fb80436d2..17a3fa2979e8ae5c5a56f88eda448f635c3e132c 100644 (file)
@@ -49,6 +49,7 @@ struct machine_desc {
        bool                    (*smp_init)(void);
        void                    (*fixup)(struct tag *, char **,
                                         struct meminfo *);
+       void                    (*init_meminfo)(void);
        void                    (*reserve)(void);/* reserve mem blocks  */
        void                    (*map_io)(void);/* IO mapping function  */
        void                    (*init_early)(void);
index fc82a88f5b69e556e9235583364b5149b2572b66..5506618119f923b3fa6e0484b3552c6d0dbc1e5d 100644 (file)
@@ -41,6 +41,14 @@ extern void mcpm_entry_point(void);
  */
 void mcpm_set_entry_vector(unsigned cpu, unsigned cluster, void *ptr);
 
+/*
+ * This sets an early poke i.e a value to be poked into some address
+ * from very early assembly code before the CPU is ungated.  The
+ * address must be physical, and if 0 then nothing will happen.
+ */
+void mcpm_set_early_poke(unsigned cpu, unsigned cluster,
+                        unsigned long poke_phys_addr, unsigned long poke_val);
+
 /*
  * CPU/cluster power operations API for higher subsystems to use.
  */
index e750a938fd3ce283ccd351cb73ed9c3d8df84e75..6748d6295a1a07ec23738d660dafb88489f99595 100644 (file)
  * so that all we need to do is modify the 8-bit constant field.
  */
 #define __PV_BITS_31_24        0x81000000
+#define __PV_BITS_7_0  0x81
+
+extern phys_addr_t (*arch_virt_to_idmap) (unsigned long x);
+extern u64 __pv_phys_offset;
+extern u64 __pv_offset;
+extern void fixup_pv_table(const void *, unsigned long);
+extern const void *__pv_table_begin, *__pv_table_end;
 
-extern unsigned long __pv_phys_offset;
 #define PHYS_OFFSET __pv_phys_offset
 
 #define __pv_stub(from,to,instr,type)                  \
@@ -185,22 +191,58 @@ extern unsigned long __pv_phys_offset;
        : "=r" (to)                                     \
        : "r" (from), "I" (type))
 
-static inline unsigned long __virt_to_phys(unsigned long x)
+#define __pv_stub_mov_hi(t)                            \
+       __asm__ volatile("@ __pv_stub_mov\n"            \
+       "1:     mov     %R0, %1\n"                      \
+       "       .pushsection .pv_table,\"a\"\n"         \
+       "       .long   1b\n"                           \
+       "       .popsection\n"                          \
+       : "=r" (t)                                      \
+       : "I" (__PV_BITS_7_0))
+
+#define __pv_add_carry_stub(x, y)                      \
+       __asm__ volatile("@ __pv_add_carry_stub\n"      \
+       "1:     adds    %Q0, %1, %2\n"                  \
+       "       adc     %R0, %R0, #0\n"                 \
+       "       .pushsection .pv_table,\"a\"\n"         \
+       "       .long   1b\n"                           \
+       "       .popsection\n"                          \
+       : "+r" (y)                                      \
+       : "r" (x), "I" (__PV_BITS_31_24)                \
+       : "cc")
+
+static inline phys_addr_t __virt_to_phys(unsigned long x)
 {
-       unsigned long t;
-       __pv_stub(x, t, "add", __PV_BITS_31_24);
+       phys_addr_t t;
+
+       if (sizeof(phys_addr_t) == 4) {
+               __pv_stub(x, t, "add", __PV_BITS_31_24);
+       } else {
+               __pv_stub_mov_hi(t);
+               __pv_add_carry_stub(x, t);
+       }
        return t;
 }
 
-static inline unsigned long __phys_to_virt(unsigned long x)
+static inline unsigned long __phys_to_virt(phys_addr_t x)
 {
        unsigned long t;
        __pv_stub(x, t, "sub", __PV_BITS_31_24);
        return t;
 }
+
 #else
-#define __virt_to_phys(x)      ((x) - PAGE_OFFSET + PHYS_OFFSET)
-#define __phys_to_virt(x)      ((x) - PHYS_OFFSET + PAGE_OFFSET)
+
+static inline phys_addr_t __virt_to_phys(unsigned long x)
+{
+       return (phys_addr_t)x - PAGE_OFFSET + PHYS_OFFSET;
+}
+
+static inline unsigned long __phys_to_virt(phys_addr_t x)
+{
+       return x - PHYS_OFFSET + PAGE_OFFSET;
+}
+
 #endif
 #endif
 #endif /* __ASSEMBLY__ */
@@ -238,16 +280,31 @@ static inline phys_addr_t virt_to_phys(const volatile void *x)
 
 static inline void *phys_to_virt(phys_addr_t x)
 {
-       return (void *)(__phys_to_virt((unsigned long)(x)));
+       return (void *)__phys_to_virt(x);
 }
 
 /*
  * Drivers should NOT use these either.
  */
 #define __pa(x)                        __virt_to_phys((unsigned long)(x))
-#define __va(x)                        ((void *)__phys_to_virt((unsigned long)(x)))
+#define __va(x)                        ((void *)__phys_to_virt((phys_addr_t)(x)))
 #define pfn_to_kaddr(pfn)      __va((pfn) << PAGE_SHIFT)
 
+/*
+ * These are for systems that have a hardware interconnect supported alias of
+ * physical memory for idmap purposes.  Most cases should leave these
+ * untouched.
+ */
+static inline phys_addr_t __virt_to_idmap(unsigned long x)
+{
+       if (arch_virt_to_idmap)
+               return arch_virt_to_idmap(x);
+       else
+               return __virt_to_phys(x);
+}
+
+#define virt_to_idmap(x)       __virt_to_idmap((unsigned long)(x))
+
 /*
  * Virtual <-> DMA view memory address translations
  * Again, these are *only* valid on the kernel direct mapped RAM
index f97ee02386ee063ba12b78786c9a6cd8a4106676..86a659a19526c75a2ba3b91ce839925cc52d26de 100644 (file)
@@ -181,6 +181,13 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
 
 #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
 
+/*
+ * We don't have huge page support for short descriptors, for the moment
+ * define empty stubs for use by pin_page_for_write.
+ */
+#define pmd_hugewillfault(pmd) (0)
+#define pmd_thp_or_huge(pmd)   (0)
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_PGTABLE_2LEVEL_H */
index 5689c18c85f5ebafb95a9bb2cc99fda227992976..39c54cfa03e9b103ef39982a43bac74d5436b791 100644 (file)
@@ -206,6 +206,9 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
 #define __HAVE_ARCH_PMD_WRITE
 #define pmd_write(pmd)         (!(pmd_val(pmd) & PMD_SECT_RDONLY))
 
+#define pmd_hugewillfault(pmd) (!pmd_young(pmd) || !pmd_write(pmd))
+#define pmd_thp_or_huge(pmd)   (pmd_huge(pmd) || pmd_trans_huge(pmd))
+
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 #define pmd_trans_huge(pmd)    (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT))
 #define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING)
index 413f3876341cd6fd2e7bc4b1c6a71873cadaa887..c3d5fc124a054c6309ffacdb2845ff22fd5bfa56 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/hw_breakpoint.h>
 #include <asm/ptrace.h>
 #include <asm/types.h>
+#include <asm/unified.h>
 
 #ifdef __KERNEL__
 #define STACK_TOP      ((current->personality & ADDR_LIMIT_32BIT) ? \
@@ -87,6 +88,17 @@ unsigned long get_wchan(struct task_struct *p);
 #define KSTK_EIP(tsk)  task_pt_regs(tsk)->ARM_pc
 #define KSTK_ESP(tsk)  task_pt_regs(tsk)->ARM_sp
 
+#ifdef CONFIG_SMP
+#define __ALT_SMP_ASM(smp, up)                                         \
+       "9998:  " smp "\n"                                              \
+       "       .pushsection \".alt.smp.init\", \"a\"\n"                \
+       "       .long   9998b\n"                                        \
+       "       " up "\n"                                               \
+       "       .popsection\n"
+#else
+#define __ALT_SMP_ASM(smp, up) up
+#endif
+
 /*
  * Prefetching support - only ARMv5.
  */
@@ -97,17 +109,22 @@ static inline void prefetch(const void *ptr)
 {
        __asm__ __volatile__(
                "pld\t%a0"
-               :
-               : "p" (ptr)
-               : "cc");
+               :: "p" (ptr));
 }
 
+#if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
 #define ARCH_HAS_PREFETCHW
-#define prefetchw(ptr) prefetch(ptr)
-
-#define ARCH_HAS_SPINLOCK_PREFETCH
-#define spin_lock_prefetch(x) do { } while (0)
-
+static inline void prefetchw(const void *ptr)
+{
+       __asm__ __volatile__(
+               ".arch_extension        mp\n"
+               __ALT_SMP_ASM(
+                       WASM(pldw)              "\t%a0",
+                       WASM(pld)               "\t%a0"
+               )
+               :: "p" (ptr));
+}
+#endif
 #endif
 
 #define HAVE_ARCH_PICK_MMAP_LAYOUT
index a8cae71caceb3fb89c1ec949063b7a0d621dbdca..22a3b9b5d4a16fd4ece50bdfc83859f6ea38352f 100644 (file)
@@ -84,6 +84,8 @@ extern void arch_send_call_function_single_ipi(int cpu);
 extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
 extern void arch_send_wakeup_ipi_mask(const struct cpumask *mask);
 
+extern int register_ipi_completion(struct completion *completion, int cpu);
+
 struct smp_operations {
 #ifdef CONFIG_SMP
        /*
index 4f2c28060c9aa227c47e73ac6557c45add91128f..ef3c6072aa45345ae4594f22aebbe9a9ebc538f1 100644 (file)
@@ -5,21 +5,13 @@
 #error SMP not supported on pre-ARMv6 CPUs
 #endif
 
-#include <asm/processor.h>
+#include <linux/prefetch.h>
 
 /*
  * sev and wfe are ARMv6K extensions.  Uniprocessor ARMv6 may not have the K
  * extensions, so when running on UP, we have to patch these instructions away.
  */
-#define ALT_SMP(smp, up)                                       \
-       "9998:  " smp "\n"                                      \
-       "       .pushsection \".alt.smp.init\", \"a\"\n"        \
-       "       .long   9998b\n"                                \
-       "       " up "\n"                                       \
-       "       .popsection\n"
-
 #ifdef CONFIG_THUMB2_KERNEL
-#define SEV            ALT_SMP("sev.w", "nop.w")
 /*
  * For Thumb-2, special care is needed to ensure that the conditional WFE
  * instruction really does assemble to exactly 4 bytes (as required by
  * the assembler won't change IT instructions which are explicitly present
  * in the input.
  */
-#define WFE(cond)      ALT_SMP(                \
+#define WFE(cond)      __ALT_SMP_ASM(          \
        "it " cond "\n\t"                       \
        "wfe" cond ".n",                        \
                                                \
        "nop.w"                                 \
 )
 #else
-#define SEV            ALT_SMP("sev", "nop")
-#define WFE(cond)      ALT_SMP("wfe" cond, "nop")
+#define WFE(cond)      __ALT_SMP_ASM("wfe" cond, "nop")
 #endif
 
+#define SEV            __ALT_SMP_ASM(WASM(sev), WASM(nop))
+
 static inline void dsb_sev(void)
 {
 #if __LINUX_ARM_ARCH__ >= 7
@@ -77,6 +70,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
        u32 newval;
        arch_spinlock_t lockval;
 
+       prefetchw(&lock->slock);
        __asm__ __volatile__(
 "1:    ldrex   %0, [%3]\n"
 "      add     %1, %0, %4\n"
@@ -100,6 +94,7 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock)
        unsigned long contended, res;
        u32 slock;
 
+       prefetchw(&lock->slock);
        do {
                __asm__ __volatile__(
                "       ldrex   %0, [%3]\n"
@@ -127,10 +122,14 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock)
        dsb_sev();
 }
 
+static inline int arch_spin_value_unlocked(arch_spinlock_t lock)
+{
+       return lock.tickets.owner == lock.tickets.next;
+}
+
 static inline int arch_spin_is_locked(arch_spinlock_t *lock)
 {
-       struct __raw_tickets tickets = ACCESS_ONCE(lock->tickets);
-       return tickets.owner != tickets.next;
+       return !arch_spin_value_unlocked(ACCESS_ONCE(*lock));
 }
 
 static inline int arch_spin_is_contended(arch_spinlock_t *lock)
@@ -152,6 +151,7 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
 {
        unsigned long tmp;
 
+       prefetchw(&rw->lock);
        __asm__ __volatile__(
 "1:    ldrex   %0, [%1]\n"
 "      teq     %0, #0\n"
@@ -170,6 +170,7 @@ static inline int arch_write_trylock(arch_rwlock_t *rw)
 {
        unsigned long contended, res;
 
+       prefetchw(&rw->lock);
        do {
                __asm__ __volatile__(
                "       ldrex   %0, [%2]\n"
@@ -203,7 +204,7 @@ static inline void arch_write_unlock(arch_rwlock_t *rw)
 }
 
 /* write_can_lock - would write_trylock() succeed? */
-#define arch_write_can_lock(x)         ((x)->lock == 0)
+#define arch_write_can_lock(x)         (ACCESS_ONCE((x)->lock) == 0)
 
 /*
  * Read locks are a bit more hairy:
@@ -221,6 +222,7 @@ static inline void arch_read_lock(arch_rwlock_t *rw)
 {
        unsigned long tmp, tmp2;
 
+       prefetchw(&rw->lock);
        __asm__ __volatile__(
 "1:    ldrex   %0, [%2]\n"
 "      adds    %0, %0, #1\n"
@@ -241,6 +243,7 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
 
        smp_mb();
 
+       prefetchw(&rw->lock);
        __asm__ __volatile__(
 "1:    ldrex   %0, [%2]\n"
 "      sub     %0, %0, #1\n"
@@ -259,6 +262,7 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
 {
        unsigned long contended, res;
 
+       prefetchw(&rw->lock);
        do {
                __asm__ __volatile__(
                "       ldrex   %0, [%2]\n"
@@ -280,7 +284,7 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
 }
 
 /* read_can_lock - would read_trylock() succeed? */
-#define arch_read_can_lock(x)          ((x)->lock < 0x80000000)
+#define arch_read_can_lock(x)          (ACCESS_ONCE((x)->lock) < 0x80000000)
 
 #define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
 #define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
index b262d2f8b4784eba5b6805d431468c285c434b88..47663fcb10ad7aad7e3bc87f31636a7a77342e36 100644 (file)
@@ -25,7 +25,7 @@ typedef struct {
 #define __ARCH_SPIN_LOCK_UNLOCKED      { { 0 } }
 
 typedef struct {
-       volatile unsigned int lock;
+       u32 lock;
 } arch_rwlock_t;
 
 #define __ARCH_RW_LOCK_UNLOCKED                { 0 }
index 38960264040cd989068b7e897979194bd5d30bc4..def9e570199f90a0c42dc7da0f8998fba6a0ab39 100644 (file)
@@ -560,37 +560,6 @@ static inline void __flush_bp_all(void)
                asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero));
 }
 
-#include <asm/cputype.h>
-#ifdef CONFIG_ARM_ERRATA_798181
-static inline int erratum_a15_798181(void)
-{
-       unsigned int midr = read_cpuid_id();
-
-       /* Cortex-A15 r0p0..r3p2 affected */
-       if ((midr & 0xff0ffff0) != 0x410fc0f0 || midr > 0x413fc0f2)
-               return 0;
-       return 1;
-}
-
-static inline void dummy_flush_tlb_a15_erratum(void)
-{
-       /*
-        * Dummy TLBIMVAIS. Using the unmapped address 0 and ASID 0.
-        */
-       asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0));
-       dsb(ish);
-}
-#else
-static inline int erratum_a15_798181(void)
-{
-       return 0;
-}
-
-static inline void dummy_flush_tlb_a15_erratum(void)
-{
-}
-#endif
-
 /*
  *     flush_pmd_entry
  *
@@ -697,4 +666,21 @@ extern void flush_bp_all(void);
 
 #endif
 
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_ARM_ERRATA_798181
+extern void erratum_a15_798181_init(void);
+#else
+static inline void erratum_a15_798181_init(void) {}
+#endif
+extern bool (*erratum_a15_798181_handler)(void);
+
+static inline bool erratum_a15_798181(void)
+{
+       if (unlikely(IS_ENABLED(CONFIG_ARM_ERRATA_798181) &&
+               erratum_a15_798181_handler))
+               return erratum_a15_798181_handler();
+       return false;
+}
+#endif
+
 #endif
index f5989f46b4d2d450f18b24faa946de750394ec13..b88beaba6b4a5cf9c0ccded73723c4ea41539167 100644 (file)
@@ -38,6 +38,8 @@
 #ifdef __ASSEMBLY__
 #define W(instr)       instr.w
 #define BSYM(sym)      sym + 1
+#else
+#define WASM(instr)    #instr ".w"
 #endif
 
 #else  /* !CONFIG_THUMB2_KERNEL */
@@ -50,6 +52,8 @@
 #ifdef __ASSEMBLY__
 #define W(instr)       instr
 #define BSYM(sym)      sym
+#else
+#define WASM(instr)    #instr
 #endif
 
 #endif /* CONFIG_THUMB2_KERNEL */
diff --git a/arch/arm/include/debug/efm32.S b/arch/arm/include/debug/efm32.S
new file mode 100644 (file)
index 0000000..2265a19
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2013 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define UARTn_CMD              0x000c
+#define UARTn_CMD_TXEN                 0x0004
+
+#define        UARTn_STATUS            0x0010
+#define        UARTn_STATUS_TXC                0x0020
+#define        UARTn_STATUS_TXBL               0x0040
+
+#define        UARTn_TXDATA            0x0034
+
+               .macro  addruart, rx, tmp
+               ldr     \rx, =(CONFIG_DEBUG_UART_PHYS)
+
+               /*
+                * enable TX. The driver might disable it to save energy. We
+                * don't care about disabling at the end as during debug power
+                * consumption isn't that important.
+                */
+               ldr     \tmp, =(UARTn_CMD_TXEN)
+               str     \tmp, [\rx, #UARTn_CMD]
+               .endm
+
+               .macro  senduart,rd,rx
+               strb    \rd, [\rx, #UARTn_TXDATA]
+               .endm
+
+               .macro  waituart,rd,rx
+1001:          ldr     \rd, [\rx, #UARTn_STATUS]
+               tst     \rd, #UARTn_STATUS_TXBL
+               beq     1001b
+               .endm
+
+               .macro  busyuart,rd,rx
+1001:          ldr     \rd, [\rx, UARTn_STATUS]
+               tst     \rd, #UARTn_STATUS_TXC
+               bne     1001b
+               .endm
index 18d76fd5a2afb2bf27b91980f29c77094e6638c0..70a1c9da30ca39d4d4d79e8e73c3b8aec0d607e3 100644 (file)
@@ -7,6 +7,7 @@ header-y += hwcap.h
 header-y += ioctls.h
 header-y += kvm_para.h
 header-y += mman.h
+header-y += perf_regs.h
 header-y += posix_types.h
 header-y += ptrace.h
 header-y += setup.h
diff --git a/arch/arm/include/uapi/asm/perf_regs.h b/arch/arm/include/uapi/asm/perf_regs.h
new file mode 100644 (file)
index 0000000..ce59448
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _ASM_ARM_PERF_REGS_H
+#define _ASM_ARM_PERF_REGS_H
+
+enum perf_event_arm_regs {
+       PERF_REG_ARM_R0,
+       PERF_REG_ARM_R1,
+       PERF_REG_ARM_R2,
+       PERF_REG_ARM_R3,
+       PERF_REG_ARM_R4,
+       PERF_REG_ARM_R5,
+       PERF_REG_ARM_R6,
+       PERF_REG_ARM_R7,
+       PERF_REG_ARM_R8,
+       PERF_REG_ARM_R9,
+       PERF_REG_ARM_R10,
+       PERF_REG_ARM_FP,
+       PERF_REG_ARM_IP,
+       PERF_REG_ARM_SP,
+       PERF_REG_ARM_LR,
+       PERF_REG_ARM_PC,
+       PERF_REG_ARM_MAX,
+};
+#endif /* _ASM_ARM_PERF_REGS_H */
index 5140df5f23aa485214914a8dfbfdf31dc04a5691..9b818ca3610bce4d61cf149ec62c0ebd2de8673c 100644 (file)
@@ -78,6 +78,7 @@ obj-$(CONFIG_CPU_XSC3)                += xscale-cp0.o
 obj-$(CONFIG_CPU_MOHAWK)       += xscale-cp0.o
 obj-$(CONFIG_CPU_PJ4)          += pj4-cp0.o
 obj-$(CONFIG_IWMMXT)           += iwmmxt.o
+obj-$(CONFIG_PERF_EVENTS)      += perf_regs.o
 obj-$(CONFIG_HW_PERF_EVENTS)   += perf_event.o perf_event_cpu.o
 AFLAGS_iwmmxt.o                        := -Wa,-mcpu=iwmmxt
 obj-$(CONFIG_ARM_CPU_TOPOLOGY)  += topology.o
index 60d3b738d4200987e76c75b2e9da513920087a89..1f031ddd0667a3e842317a90c59db3acc2284894 100644 (file)
@@ -155,4 +155,5 @@ EXPORT_SYMBOL(__gnu_mcount_nc);
 
 #ifdef CONFIG_ARM_PATCH_PHYS_VIRT
 EXPORT_SYMBOL(__pv_phys_offset);
+EXPORT_SYMBOL(__pv_offset);
 #endif
index de23a9beed1333d86d1143a7b31613ff7376440d..39f89fbd5111ee9f0a96d6712e1f0f2ba308147d 100644 (file)
 #ifdef CONFIG_CONTEXT_TRACKING
        .if     \save
        stmdb   sp!, {r0-r3, ip, lr}
-       bl      user_exit
+       bl      context_tracking_user_exit
        ldmia   sp!, {r0-r3, ip, lr}
        .else
-       bl      user_exit
+       bl      context_tracking_user_exit
        .endif
 #endif
        .endm
 #ifdef CONFIG_CONTEXT_TRACKING
        .if     \save
        stmdb   sp!, {r0-r3, ip, lr}
-       bl      user_enter
+       bl      context_tracking_user_enter
        ldmia   sp!, {r0-r3, ip, lr}
        .else
-       bl      user_enter
+       bl      context_tracking_user_enter
        .endif
 #endif
        .endm
index 476de57dcef284602e126e29e2da03465df8ff09..0f6c6d1fe447918dd5d98193b53a95a6e0a0fc1e 100644 (file)
@@ -555,6 +555,14 @@ ENTRY(fixup_smp)
        ldmfd   sp!, {r4 - r6, pc}
 ENDPROC(fixup_smp)
 
+#ifdef __ARMEB_
+#define LOW_OFFSET     0x4
+#define HIGH_OFFSET    0x0
+#else
+#define LOW_OFFSET     0x0
+#define HIGH_OFFSET    0x4
+#endif
+
 #ifdef CONFIG_ARM_PATCH_PHYS_VIRT
 
 /* __fixup_pv_table - patch the stub instructions with the delta between
@@ -565,17 +573,20 @@ ENDPROC(fixup_smp)
        __HEAD
 __fixup_pv_table:
        adr     r0, 1f
-       ldmia   r0, {r3-r5, r7}
-       sub     r3, r0, r3      @ PHYS_OFFSET - PAGE_OFFSET
+       ldmia   r0, {r3-r7}
+       mvn     ip, #0
+       subs    r3, r0, r3      @ PHYS_OFFSET - PAGE_OFFSET
        add     r4, r4, r3      @ adjust table start address
        add     r5, r5, r3      @ adjust table end address
-       add     r7, r7, r3      @ adjust __pv_phys_offset address
-       str     r8, [r7]        @ save computed PHYS_OFFSET to __pv_phys_offset
+       add     r6, r6, r3      @ adjust __pv_phys_offset address
+       add     r7, r7, r3      @ adjust __pv_offset address
+       str     r8, [r6, #LOW_OFFSET]   @ save computed PHYS_OFFSET to __pv_phys_offset
+       strcc   ip, [r7, #HIGH_OFFSET]  @ save to __pv_offset high bits
        mov     r6, r3, lsr #24 @ constant for add/sub instructions
        teq     r3, r6, lsl #24 @ must be 16MiB aligned
 THUMB( it      ne              @ cross section branch )
        bne     __error
-       str     r6, [r7, #4]    @ save to __pv_offset
+       str     r3, [r7, #LOW_OFFSET]   @ save to __pv_offset low bits
        b       __fixup_a_pv_table
 ENDPROC(__fixup_pv_table)
 
@@ -584,10 +595,19 @@ ENDPROC(__fixup_pv_table)
        .long   __pv_table_begin
        .long   __pv_table_end
 2:     .long   __pv_phys_offset
+       .long   __pv_offset
 
        .text
 __fixup_a_pv_table:
+       adr     r0, 3f
+       ldr     r6, [r0]
+       add     r6, r6, r3
+       ldr     r0, [r6, #HIGH_OFFSET]  @ pv_offset high word
+       ldr     r6, [r6, #LOW_OFFSET]   @ pv_offset low word
+       mov     r6, r6, lsr #24
+       cmn     r0, #1
 #ifdef CONFIG_THUMB2_KERNEL
+       moveq   r0, #0x200000   @ set bit 21, mov to mvn instruction
        lsls    r6, #24
        beq     2f
        clz     r7, r6
@@ -601,18 +621,28 @@ __fixup_a_pv_table:
        b       2f
 1:     add     r7, r3
        ldrh    ip, [r7, #2]
-       and     ip, 0x8f00
-       orr     ip, r6  @ mask in offset bits 31-24
+       tst     ip, #0x4000
+       and     ip, #0x8f00
+       orrne   ip, r6  @ mask in offset bits 31-24
+       orreq   ip, r0  @ mask in offset bits 7-0
        strh    ip, [r7, #2]
+       ldrheq  ip, [r7]
+       biceq   ip, #0x20
+       orreq   ip, ip, r0, lsr #16
+       strheq  ip, [r7]
 2:     cmp     r4, r5
        ldrcc   r7, [r4], #4    @ use branch for delay slot
        bcc     1b
        bx      lr
 #else
+       moveq   r0, #0x400000   @ set bit 22, mov to mvn instruction
        b       2f
 1:     ldr     ip, [r7, r3]
        bic     ip, ip, #0x000000ff
-       orr     ip, ip, r6      @ mask in offset bits 31-24
+       tst     ip, #0xf00      @ check the rotation field
+       orrne   ip, ip, r6      @ mask in offset bits 31-24
+       biceq   ip, ip, #0x400000       @ clear bit 22
+       orreq   ip, ip, r0      @ mask in offset bits 7-0
        str     ip, [r7, r3]
 2:     cmp     r4, r5
        ldrcc   r7, [r4], #4    @ use branch for delay slot
@@ -621,28 +651,29 @@ __fixup_a_pv_table:
 #endif
 ENDPROC(__fixup_a_pv_table)
 
+3:     .long __pv_offset
+
 ENTRY(fixup_pv_table)
        stmfd   sp!, {r4 - r7, lr}
-       ldr     r2, 2f                  @ get address of __pv_phys_offset
        mov     r3, #0                  @ no offset
        mov     r4, r0                  @ r0 = table start
        add     r5, r0, r1              @ r1 = table size
-       ldr     r6, [r2, #4]            @ get __pv_offset
        bl      __fixup_a_pv_table
        ldmfd   sp!, {r4 - r7, pc}
 ENDPROC(fixup_pv_table)
 
-       .align
-2:     .long   __pv_phys_offset
-
        .data
        .globl  __pv_phys_offset
        .type   __pv_phys_offset, %object
 __pv_phys_offset:
-       .long   0
-       .size   __pv_phys_offset, . - __pv_phys_offset
+       .quad   0
+       .size   __pv_phys_offset, . -__pv_phys_offset
+
+       .globl  __pv_offset
+       .type   __pv_offset, %object
 __pv_offset:
-       .long   0
+       .quad   0
+       .size   __pv_offset, . -__pv_offset
 #endif
 
 #include "head-common.S"
index e186ee1e63f6c85261f96844a594080e719c2e07..bc3f2efa0d86b4ff55d6b19833eae688b111fd27 100644 (file)
@@ -256,12 +256,11 @@ validate_event(struct pmu_hw_events *hw_events,
               struct perf_event *event)
 {
        struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
-       struct pmu *leader_pmu = event->group_leader->pmu;
 
        if (is_software_event(event))
                return 1;
 
-       if (event->pmu != leader_pmu || event->state < PERF_EVENT_STATE_OFF)
+       if (event->state < PERF_EVENT_STATE_OFF)
                return 1;
 
        if (event->state == PERF_EVENT_STATE_OFF && !event->attr.enable_on_exec)
diff --git a/arch/arm/kernel/perf_regs.c b/arch/arm/kernel/perf_regs.c
new file mode 100644 (file)
index 0000000..6e4379c
--- /dev/null
@@ -0,0 +1,30 @@
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/perf_event.h>
+#include <linux/bug.h>
+#include <asm/perf_regs.h>
+#include <asm/ptrace.h>
+
+u64 perf_reg_value(struct pt_regs *regs, int idx)
+{
+       if (WARN_ON_ONCE((u32)idx >= PERF_REG_ARM_MAX))
+               return 0;
+
+       return regs->uregs[idx];
+}
+
+#define REG_RESERVED (~((1ULL << PERF_REG_ARM_MAX) - 1))
+
+int perf_reg_validate(u64 mask)
+{
+       if (!mask || mask & REG_RESERVED)
+               return -EINVAL;
+
+       return 0;
+}
+
+u64 perf_reg_abi(struct task_struct *task)
+{
+       return PERF_SAMPLE_REGS_ABI_32;
+}
index 0e1e2b3afa45864b5776c177ceb5001402e31681..6b4ce802ac4ea3e2d88bbe04adce6713651fb066 100644 (file)
@@ -73,6 +73,8 @@ __setup("fpe=", fpe_setup);
 #endif
 
 extern void paging_init(const struct machine_desc *desc);
+extern void early_paging_init(const struct machine_desc *,
+                             struct proc_info_list *);
 extern void sanity_check_meminfo(void);
 extern enum reboot_mode reboot_mode;
 extern void setup_dma_zone(const struct machine_desc *desc);
@@ -599,6 +601,8 @@ static void __init setup_processor(void)
        elf_hwcap &= ~(HWCAP_THUMB | HWCAP_IDIVT);
 #endif
 
+       erratum_a15_798181_init();
+
        feat_v6_fixup();
 
        cacheid_init();
@@ -878,6 +882,8 @@ void __init setup_arch(char **cmdline_p)
        parse_early_param();
 
        sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL);
+
+       early_paging_init(mdesc, lookup_processor_type(read_cpuid_id()));
        sanity_check_meminfo();
        arm_memblock_init(&meminfo, mdesc);
 
index db1536b8b30b497fe11923dfe9f67a72f86f7954..62246020191138e7d3bcdc90cf5d7c645b7ec1b9 100644 (file)
@@ -55,6 +55,7 @@
  * specific registers and some other data for resume.
  *  r0 = suspend function arg0
  *  r1 = suspend function
+ *  r2 = MPIDR value the resuming CPU will use
  */
 ENTRY(__cpu_suspend)
        stmfd   sp!, {r4 - r11, lr}
@@ -67,23 +68,18 @@ ENTRY(__cpu_suspend)
        mov     r5, sp                  @ current virtual SP
        add     r4, r4, #12             @ Space for pgd, virt sp, phys resume fn
        sub     sp, sp, r4              @ allocate CPU state on stack
-       stmfd   sp!, {r0, r1}           @ save suspend func arg and pointer
-       add     r0, sp, #8              @ save pointer to save block
-       mov     r1, r4                  @ size of save block
-       mov     r2, r5                  @ virtual SP
        ldr     r3, =sleep_save_sp
+       stmfd   sp!, {r0, r1}           @ save suspend func arg and pointer
        ldr     r3, [r3, #SLEEP_SAVE_SP_VIRT]
-       ALT_SMP(mrc p15, 0, r9, c0, c0, 5)
-        ALT_UP_B(1f)
-       ldr     r8, =mpidr_hash
-       /*
-        * This ldmia relies on the memory layout of the mpidr_hash
-        * struct mpidr_hash.
-        */
-       ldmia   r8, {r4-r7}     @ r4 = mpidr mask (r5,r6,r7) = l[0,1,2] shifts
-       compute_mpidr_hash      lr, r5, r6, r7, r9, r4
-       add     r3, r3, lr, lsl #2
-1:
+       ALT_SMP(ldr r0, =mpidr_hash)
+       ALT_UP_B(1f)
+       /* This ldmia relies on the memory layout of the mpidr_hash struct */
+       ldmia   r0, {r1, r6-r8} @ r1 = mpidr mask (r6,r7,r8) = l[0,1,2] shifts
+       compute_mpidr_hash      r0, r6, r7, r8, r2, r1
+       add     r3, r3, r0, lsl #2
+1:     mov     r2, r5                  @ virtual SP
+       mov     r1, r4                  @ size of save block
+       add     r0, sp, #8              @ pointer to save block
        bl      __cpu_suspend_save
        adr     lr, BSYM(cpu_suspend_abort)
        ldmfd   sp!, {r0, pc}           @ call suspend fn
index 72024ea8a3a6c07038103e153527cb2454e4552f..5c820cbcf918140873650f9a4a61376d4c951bcf 100644 (file)
@@ -66,6 +66,7 @@ enum ipi_msg_type {
        IPI_CALL_FUNC,
        IPI_CALL_FUNC_SINGLE,
        IPI_CPU_STOP,
+       IPI_COMPLETION,
 };
 
 static DECLARE_COMPLETION(cpu_running);
@@ -80,7 +81,7 @@ void __init smp_set_ops(struct smp_operations *ops)
 
 static unsigned long get_arch_pgd(pgd_t *pgd)
 {
-       phys_addr_t pgdir = virt_to_phys(pgd);
+       phys_addr_t pgdir = virt_to_idmap(pgd);
        BUG_ON(pgdir & ARCH_PGD_MASK);
        return pgdir >> ARCH_PGD_SHIFT;
 }
@@ -456,6 +457,7 @@ static const char *ipi_types[NR_IPI] = {
        S(IPI_CALL_FUNC, "Function call interrupts"),
        S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"),
        S(IPI_CPU_STOP, "CPU stop interrupts"),
+       S(IPI_COMPLETION, "completion interrupts"),
 };
 
 void show_ipi_list(struct seq_file *p, int prec)
@@ -515,6 +517,19 @@ static void ipi_cpu_stop(unsigned int cpu)
                cpu_relax();
 }
 
+static DEFINE_PER_CPU(struct completion *, cpu_completion);
+
+int register_ipi_completion(struct completion *completion, int cpu)
+{
+       per_cpu(cpu_completion, cpu) = completion;
+       return IPI_COMPLETION;
+}
+
+static void ipi_complete(unsigned int cpu)
+{
+       complete(per_cpu(cpu_completion, cpu));
+}
+
 /*
  * Main handler for inter-processor interrupts
  */
@@ -565,6 +580,12 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
                irq_exit();
                break;
 
+       case IPI_COMPLETION:
+               irq_enter();
+               ipi_complete(cpu);
+               irq_exit();
+               break;
+
        default:
                printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n",
                       cpu, ipinr);
index 83ccca303df83c4a1f40dce35f324153d979ad16..95d063620b76a6f706bccc23635537ed4bceb01a 100644 (file)
@@ -70,6 +70,40 @@ static inline void ipi_flush_bp_all(void *ignored)
        local_flush_bp_all();
 }
 
+#ifdef CONFIG_ARM_ERRATA_798181
+bool (*erratum_a15_798181_handler)(void);
+
+static bool erratum_a15_798181_partial(void)
+{
+       asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0));
+       dsb(ish);
+       return false;
+}
+
+static bool erratum_a15_798181_broadcast(void)
+{
+       asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0));
+       dsb(ish);
+       return true;
+}
+
+void erratum_a15_798181_init(void)
+{
+       unsigned int midr = read_cpuid_id();
+       unsigned int revidr = read_cpuid(CPUID_REVIDR);
+
+       /* Cortex-A15 r0p0..r3p2 w/o ECO fix affected */
+       if ((midr & 0xff0ffff0) != 0x410fc0f0 || midr > 0x413fc0f2 ||
+           (revidr & 0x210) == 0x210) {
+               return;
+       }
+       if (revidr & 0x10)
+               erratum_a15_798181_handler = erratum_a15_798181_partial;
+       else
+               erratum_a15_798181_handler = erratum_a15_798181_broadcast;
+}
+#endif
+
 static void ipi_flush_tlb_a15_erratum(void *arg)
 {
        dmb();
@@ -80,7 +114,6 @@ static void broadcast_tlb_a15_erratum(void)
        if (!erratum_a15_798181())
                return;
 
-       dummy_flush_tlb_a15_erratum();
        smp_call_function(ipi_flush_tlb_a15_erratum, NULL, 1);
 }
 
@@ -92,7 +125,6 @@ static void broadcast_tlb_mm_a15_erratum(struct mm_struct *mm)
        if (!erratum_a15_798181())
                return;
 
-       dummy_flush_tlb_a15_erratum();
        this_cpu = get_cpu();
        a15_erratum_get_cpumask(this_cpu, mm, &mask);
        smp_call_function_many(&mask, ipi_flush_tlb_a15_erratum, NULL, 1);
index 41cf3cbf756de473be3bb1ebb268445aeacadc5d..2835d35234ca459f4d7086a6f811ff35652a6a11 100644 (file)
@@ -10,7 +10,7 @@
 #include <asm/suspend.h>
 #include <asm/tlbflush.h>
 
-extern int __cpu_suspend(unsigned long, int (*)(unsigned long));
+extern int __cpu_suspend(unsigned long, int (*)(unsigned long), u32 cpuid);
 extern void cpu_resume_mmu(void);
 
 #ifdef CONFIG_MMU
@@ -21,6 +21,7 @@ extern void cpu_resume_mmu(void);
 int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
 {
        struct mm_struct *mm = current->active_mm;
+       u32 __mpidr = cpu_logical_map(smp_processor_id());
        int ret;
 
        if (!idmap_pgd)
@@ -32,7 +33,7 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
         * resume (indicated by a zero return code), we need to switch
         * back to the correct page tables.
         */
-       ret = __cpu_suspend(arg, fn);
+       ret = __cpu_suspend(arg, fn, __mpidr);
        if (ret == 0) {
                cpu_switch_mm(mm->pgd, mm);
                local_flush_bp_all();
@@ -44,7 +45,8 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
 #else
 int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
 {
-       return __cpu_suspend(arg, fn);
+       u32 __mpidr = cpu_logical_map(smp_processor_id());
+       return __cpu_suspend(arg, fn, __mpidr);
 }
 #define        idmap_pgd       NULL
 #endif
index 71e08baee209387f899e14a32fa32e02682b0ae8..c02ba4af599f417113fdb2c260270ae7162575e6 100644 (file)
@@ -58,14 +58,14 @@ static const struct kvm_irq_level a15_vtimer_irq = {
  */
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 {
-       struct kvm_regs *cpu_reset;
+       struct kvm_regs *reset_regs;
        const struct kvm_irq_level *cpu_vtimer_irq;
 
        switch (vcpu->arch.target) {
        case KVM_ARM_TARGET_CORTEX_A15:
                if (vcpu->vcpu_id > a15_max_cpu_idx)
                        return -EINVAL;
-               cpu_reset = &a15_regs_reset;
+               reset_regs = &a15_regs_reset;
                vcpu->arch.midr = read_cpuid_id();
                cpu_vtimer_irq = &a15_vtimer_irq;
                break;
@@ -74,7 +74,7 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
        }
 
        /* Reset core registers */
-       memcpy(&vcpu->arch.regs, cpu_reset, sizeof(vcpu->arch.regs));
+       memcpy(&vcpu->arch.regs, reset_regs, sizeof(vcpu->arch.regs));
 
        /* Reset CP15 registers */
        kvm_reset_coprocs(vcpu);
index d6408d1ee543fe5e3ceabbcda01b25efb07676ba..e0c68d5bb7dc25dd3fa93dc0fa1b3899f5b09019 100644 (file)
@@ -10,6 +10,11 @@ UNWIND(      .fnstart        )
        and     r3, r0, #31             @ Get bit offset
        mov     r0, r0, lsr #5
        add     r1, r1, r0, lsl #2      @ Get word offset
+#if __LINUX_ARM_ARCH__ >= 7
+       .arch_extension mp
+       ALT_SMP(W(pldw) [r1])
+       ALT_UP(W(nop))
+#endif
        mov     r3, r2, lsl r3
 1:     ldrex   r2, [r1]
        \instr  r2, r2, r3
index 025f742dd4df6bf79b279babd264980d851f01d5..3e58d710013c3ad9b377fc76e6dad58f377e88a7 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/hardirq.h> /* for in_atomic() */
 #include <linux/gfp.h>
 #include <linux/highmem.h>
+#include <linux/hugetlb.h>
 #include <asm/current.h>
 #include <asm/page.h>
 
@@ -40,7 +41,35 @@ pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
                return 0;
 
        pmd = pmd_offset(pud, addr);
-       if (unlikely(pmd_none(*pmd) || pmd_bad(*pmd)))
+       if (unlikely(pmd_none(*pmd)))
+               return 0;
+
+       /*
+        * A pmd can be bad if it refers to a HugeTLB or THP page.
+        *
+        * Both THP and HugeTLB pages have the same pmd layout
+        * and should not be manipulated by the pte functions.
+        *
+        * Lock the page table for the destination and check
+        * to see that it's still huge and whether or not we will
+        * need to fault on write, or if we have a splitting THP.
+        */
+       if (unlikely(pmd_thp_or_huge(*pmd))) {
+               ptl = &current->mm->page_table_lock;
+               spin_lock(ptl);
+               if (unlikely(!pmd_thp_or_huge(*pmd)
+                       || pmd_hugewillfault(*pmd)
+                       || pmd_trans_splitting(*pmd))) {
+                       spin_unlock(ptl);
+                       return 0;
+               }
+
+               *ptep = NULL;
+               *ptlp = ptl;
+               return 1;
+       }
+
+       if (unlikely(pmd_bad(*pmd)))
                return 0;
 
        pte = pte_offset_map_lock(current->mm, pmd, addr, &ptl);
@@ -94,7 +123,10 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
                from += tocopy;
                n -= tocopy;
 
-               pte_unmap_unlock(pte, ptl);
+               if (pte)
+                       pte_unmap_unlock(pte, ptl);
+               else
+                       spin_unlock(ptl);
        }
        if (!atomic)
                up_read(&current->mm->mmap_sem);
@@ -147,7 +179,10 @@ __clear_user_memset(void __user *addr, unsigned long n)
                addr += tocopy;
                n -= tocopy;
 
-               pte_unmap_unlock(pte, ptl);
+               if (pte)
+                       pte_unmap_unlock(pte, ptl);
+               else
+                       spin_unlock(ptl);
        }
        up_read(&current->mm->mmap_sem);
 
index 180b3024bec3ab36cc2d7cdb62e92d7b2298d297..f607deb40f4da6a88a0778b203cdcfbbc8518ecc 100644 (file)
@@ -93,7 +93,7 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction at91rm9200_timer_irq = {
        .name           = "at91_tick",
-       .flags          = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+       .flags          = IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = at91rm9200_timer_interrupt,
        .irq            = NR_IRQS_LEGACY + AT91_ID_SYS,
 };
index 3a4bc2e1a65e73d3b2187f90f6b84a43e7ec6468..bb392320a0dd39d978bd5f1d3e861d2fce14b14c 100644 (file)
@@ -171,7 +171,7 @@ static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id)
 
 static struct irqaction at91sam926x_pit_irq = {
        .name           = "at91_tick",
-       .flags          = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+       .flags          = IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = at91sam926x_pit_interrupt,
        .irq            = NR_IRQS_LEGACY + AT91_ID_SYS,
 };
index 721a1a34dd1d86027161e66b9cfaee7161ebfd03..c40c1e2ef80fa9d1485c06669afad3caf0ea17fc 100644 (file)
 #include "at91_rstc.h"
                        .arm
 
+/*
+ * at91_ramc_base is an array void*
+ * init at NULL if only one DDR controler is present in or DT
+ */
                        .globl  at91sam9g45_restart
 
 at91sam9g45_restart:
                        ldr     r5, =at91_ramc_base             @ preload constants
                        ldr     r0, [r5]
+                       ldr     r5, [r5, #4]                    @ ddr1
+                       cmp     r5, #0
                        ldr     r4, =at91_rstc_base
                        ldr     r1, [r4]
 
@@ -30,6 +36,8 @@ at91sam9g45_restart:
 
                        .balign 32                              @ align to cache line
 
+                       strne   r2, [r5, #AT91_DDRSDRC_RTR]     @ disable DDR1 access
+                       strne   r3, [r5, #AT91_DDRSDRC_LPR]     @ power down DDR1
                        str     r2, [r0, #AT91_DDRSDRC_RTR]     @ disable DDR0 access
                        str     r3, [r0, #AT91_DDRSDRC_LPR]     @ power down DDR0
                        str     r4, [r1, #AT91_RSTC_CR]         @ reset processor
index 2919eba41ff4e908cd85f4d7eb3cc76a0e5fef56..c0e637adf65d2555adddaa1897730fc4021d04d7 100644 (file)
@@ -57,7 +57,7 @@ static irqreturn_t at91x40_timer_interrupt(int irq, void *dev_id)
 
 static struct irqaction at91x40_timer_irq = {
        .name           = "at91_tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_TIMER,
        .handler        = at91x40_timer_interrupt
 };
 
index 92b7f770615a83aaf59d5b81ef3526732185df86..4078ba93776b24ef9438f0dcc73c2f42dd859bd9 100644 (file)
@@ -176,7 +176,7 @@ static struct at24_platform_data eeprom_info = {
        .context        = (void *)0x7f00,
 };
 
-static struct snd_platform_data dm365_evm_snd_data = {
+static struct snd_platform_data dm365_evm_snd_data __maybe_unused = {
        .asp_chan_q = EVENTQ_3,
 };
 
index 52b8571b2e702a2e33b689983ca6fcc8632469bb..ce402cd21fa0a6f809963d71ca3cac3c6f650131 100644 (file)
@@ -15,8 +15,6 @@
 
 #include <mach/hardware.h>
 
-#include <linux/platform_device.h>
-
 #define DAVINCI_UART0_BASE     (IO_PHYS + 0x20000)
 #define DAVINCI_UART1_BASE     (IO_PHYS + 0x20400)
 #define DAVINCI_UART2_BASE     (IO_PHYS + 0x20800)
@@ -39,6 +37,8 @@
 #define UART_DM646X_SCR_TX_WATERMARK   0x08
 
 #ifndef __ASSEMBLY__
+#include <linux/platform_device.h>
+
 extern int davinci_serial_init(struct platform_device *);
 #endif
 
index deb4b8093b30487821b5e43663adc594ae763958..0d40b35c557cba39980ad2644e6d4a97902f9555 100644 (file)
@@ -90,6 +90,7 @@ struct clk *imx_clk_fixup_mux(const char *name, void __iomem *reg,
        init.ops = &clk_fixup_mux_ops;
        init.parent_names = parents;
        init.num_parents = num_parents;
+       init.flags = 0;
 
        fixup_mux->mux.reg = reg;
        fixup_mux->mux.shift = shift;
index c3cfa4116dc09ffe22f2227c47130be0d900945e..c6b40f3867863c7de1a52e5a1ab72acdc23f758f 100644 (file)
@@ -285,7 +285,7 @@ int __init mx27_clocks_init(unsigned long fref)
        clk_register_clkdev(clk[ata_ahb_gate], "ata", NULL);
        clk_register_clkdev(clk[rtc_ipg_gate], NULL, "imx21-rtc");
        clk_register_clkdev(clk[scc_ipg_gate], "scc", NULL);
-       clk_register_clkdev(clk[cpu_div], NULL, "cpufreq-cpu0.0");
+       clk_register_clkdev(clk[cpu_div], NULL, "cpu0");
        clk_register_clkdev(clk[emi_ahb_gate], "emi_ahb" , NULL);
 
        mxc_timer_init(MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR), MX27_INT_GPT1);
index 1a56a33199976ed66907a80bce0336a03f40dcf2..7c0dc4540aa4785270784e3f62ce2b643fd95664 100644 (file)
@@ -328,7 +328,7 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
        clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1");
        clk_register_clkdev(clk[ssi3_ipg_gate], NULL, "imx-ssi.2");
        clk_register_clkdev(clk[sdma_gate], NULL, "imx35-sdma");
-       clk_register_clkdev(clk[cpu_podf], NULL, "cpufreq-cpu0.0");
+       clk_register_clkdev(clk[cpu_podf], NULL, "cpu0");
        clk_register_clkdev(clk[iim_gate], "iim", NULL);
        clk_register_clkdev(clk[dummy], NULL, "imx2-wdt.0");
        clk_register_clkdev(clk[dummy], NULL, "imx2-wdt.1");
@@ -397,7 +397,7 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
                                mx51_spdif_xtal_sel, ARRAY_SIZE(mx51_spdif_xtal_sel));
        clk[spdif1_sel] = imx_clk_mux("spdif1_sel", MXC_CCM_CSCMR2, 2, 2,
                                spdif_sel, ARRAY_SIZE(spdif_sel));
-       clk[spdif1_pred] = imx_clk_divider("spdif1_podf", "spdif1_sel", MXC_CCM_CDCDR, 16, 3);
+       clk[spdif1_pred] = imx_clk_divider("spdif1_pred", "spdif1_sel", MXC_CCM_CDCDR, 16, 3);
        clk[spdif1_podf] = imx_clk_divider("spdif1_podf", "spdif1_pred", MXC_CCM_CDCDR, 9, 6);
        clk[spdif1_com_sel] = imx_clk_mux("spdif1_com_sel", MXC_CCM_CSCMR2, 5, 1,
                                mx51_spdif1_com_sel, ARRAY_SIZE(mx51_spdif1_com_sel));
index 85a1b51346c8db12845d3123dd7758af034e3357..90372a21087f9ef38535479ccc35aac9e37977dc 100644 (file)
@@ -233,10 +233,15 @@ put_node:
        of_node_put(np);
 }
 
-static void __init imx6q_opp_init(struct device *cpu_dev)
+static void __init imx6q_opp_init(void)
 {
        struct device_node *np;
+       struct device *cpu_dev = get_cpu_device(0);
 
+       if (!cpu_dev) {
+               pr_warn("failed to get cpu0 device\n");
+               return;
+       }
        np = of_node_get(cpu_dev->of_node);
        if (!np) {
                pr_warn("failed to find cpu0 node\n");
@@ -268,7 +273,7 @@ static void __init imx6q_init_late(void)
                imx6q_cpuidle_init();
 
        if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) {
-               imx6q_opp_init(&imx6q_cpufreq_pdev.dev);
+               imx6q_opp_init();
                platform_device_register(&imx6q_cpufreq_pdev);
        }
 }
index 64ff37ea72b17455a1b5be7600ff7a1c16ceab16..80c177c36c5f25665ada2fbf93cf2ac4b007eee6 100644 (file)
@@ -117,6 +117,17 @@ void __init imx_init_l2cache(void)
        /* Configure the L2 PREFETCH and POWER registers */
        val = readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL);
        val |= 0x70800000;
+       /*
+        * The L2 cache controller(PL310) version on the i.MX6D/Q is r3p1-50rel0
+        * The L2 cache controller(PL310) version on the i.MX6DL/SOLO/SL is r3p2
+        * But according to ARM PL310 errata: 752271
+        * ID: 752271: Double linefill feature can cause data corruption
+        * Fault Status: Present in: r3p0, r3p1, r3p1-50rel0. Fixed in r3p2
+        * Workaround: The only workaround to this erratum is to disable the
+        * double linefill feature. This is the default behavior.
+        */
+       if (cpu_is_imx6q())
+               val &= ~(1 << 30 | 1 << 23);
        writel_relaxed(val, l2x0_base + L2X0_PREFETCH_CTRL);
        val = L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN;
        writel_relaxed(val, l2x0_base + L2X0_POWER_CTRL);
index 755fd29fed4a5f407ed3107abb4154637bdf5228..06a9e2e7d007b847f650b8efbf0856a1f47978ae 100644 (file)
@@ -1,2 +1,9 @@
 /* Simple oneliner include to the PCIv3 early init */
+#ifdef CONFIG_PCI
 extern int pci_v3_early_init(void);
+#else
+static inline int pci_v3_early_init(void)
+{
+       return 0;
+}
+#endif
index 4c24303ec4816bfb6f1c4bc0695f57450a624517..58adf2fd9cfc98ea03f6b1f8cfe037ceb01bd78b 100644 (file)
@@ -140,6 +140,7 @@ int __init coherency_init(void)
                coherency_base = of_iomap(np, 0);
                coherency_cpu_base = of_iomap(np, 1);
                set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0);
+               of_node_put(np);
        }
 
        return 0;
@@ -147,9 +148,14 @@ int __init coherency_init(void)
 
 static int __init coherency_late_init(void)
 {
-       if (of_find_matching_node(NULL, of_coherency_table))
+       struct device_node *np;
+
+       np = of_find_matching_node(NULL, of_coherency_table);
+       if (np) {
                bus_register_notifier(&platform_bus_type,
                                      &mvebu_hwcc_platform_nb);
+               of_node_put(np);
+       }
        return 0;
 }
 
index 3cc4bef6401c160f2b8beb5c378889740424c546..27fc4f049474ed94b07cef00dfe3304b1165369c 100644 (file)
@@ -67,6 +67,7 @@ int __init armada_370_xp_pmsu_init(void)
                pr_info("Initializing Power Management Service Unit\n");
                pmsu_mp_base = of_iomap(np, 0);
                pmsu_reset_base = of_iomap(np, 1);
+               of_node_put(np);
        }
 
        return 0;
index f875124ff4f9e558ff9be36c08d6bbc9ab3fdf13..5175083cdb34650802288789c55a82aee8c20d08 100644 (file)
@@ -98,6 +98,7 @@ static int __init mvebu_system_controller_init(void)
                BUG_ON(!match);
                system_controller_base = of_iomap(np, 0);
                mvebu_sc = (struct mvebu_system_controller *)match->data;
+               of_node_put(np);
        }
 
        return 0;
index 1d5b5290d2af3db91f5d57b0a9c945a2ccaa2e28..b237950eb8a319f9fb879d051245cc7c6fea6968 100644 (file)
@@ -1632,7 +1632,7 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "auxclk5_src_ck",               &auxclk5_src_ck),
        CLK(NULL,       "auxclk5_ck",                   &auxclk5_ck),
        CLK(NULL,       "auxclkreq5_ck",                &auxclkreq5_ck),
-       CLK("omap-gpmc",        "fck",                  &dummy_ck),
+       CLK("50000000.gpmc",    "fck",                  &dummy_ck),
        CLK("omap_i2c.1",       "ick",                  &dummy_ck),
        CLK("omap_i2c.2",       "ick",                  &dummy_ck),
        CLK("omap_i2c.3",       "ick",                  &dummy_ck),
index c443f2e97e103702531c79b70dccebc11a85218d..4c8982ae95295f508c1fc6610f8c47d1e1c8137d 100644 (file)
@@ -143,7 +143,7 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
         * Call idle CPU cluster PM exit notifier chain
         * to restore GIC and wakeupgen context.
         */
-       if ((cx->mpu_state == PWRDM_POWER_RET) &&
+       if (dev->cpu == 0 && (cx->mpu_state == PWRDM_POWER_RET) &&
                (cx->mpu_logic_state == PWRDM_POWER_OFF))
                cpu_cluster_pm_exit();
 
index 9f4795aff48aae5eedcf874284bb88b9b3b2d777..579697adaae7dfd373285979eebeb815658f4a1d 100644 (file)
@@ -1491,8 +1491,8 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
         */
        ret = gpmc_cs_remap(cs, res.start);
        if (ret < 0) {
-               dev_err(&pdev->dev, "cannot remap GPMC CS %d to 0x%x\n",
-                       cs, res.start);
+               dev_err(&pdev->dev, "cannot remap GPMC CS %d to %pa\n",
+                       cs, &res.start);
                goto err;
        }
 
index c53609f4629485b46277aad1e0bdb5634f244c84..be271f1d585bfb5825e22edb93157dde999a6234 100644 (file)
@@ -620,7 +620,7 @@ static struct omap_mux __initdata omap3_muxmodes[] = {
                "uart1_rts", "ssi1_flag_tx", NULL, NULL,
                "gpio_149", NULL, NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART1_RX, 151,
-               "uart1_rx", "ss1_wake_tx", "mcbsp1_clkr", "mcspi4_clk",
+               "uart1_rx", "ssi1_wake_tx", "mcbsp1_clkr", "mcspi4_clk",
                "gpio_151", NULL, NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART1_TX, 148,
                "uart1_tx", "ssi1_dat_tx", NULL, NULL,
index 8708b2a9da453e91be9bc16590d48e9652b35508..89121109329533b917561f4da6ce4b335872f4c4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * OMAP4 SMP source file. It contains platform specific fucntions
+ * OMAP4 SMP source file. It contains platform specific functions
  * needed for the linux smp kernel.
  *
  * Copyright (C) 2009 Texas Instruments, Inc.
index f99f68e1e85bd3748c5965a0bd27c47d0f6d538e..b69dd9abb50aeb0003998b24d7df9063a6a41cb1 100644 (file)
@@ -158,7 +158,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
        }
 
        od = omap_device_alloc(pdev, hwmods, oh_cnt);
-       if (!od) {
+       if (IS_ERR(od)) {
                dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n",
                        oh_name);
                ret = PTR_ERR(od);
index e838ba27e443c1dd0b54042c3e4afd882ae22265..c9808c6841526204144e36a273596e6955696dc8 100644 (file)
@@ -512,6 +512,9 @@ static void __init assabet_map_io(void)
         * Its called GPCLKR0 in my SA1110 manual.
         */
        Ser1SDCR0 |= SDCR0_SUS;
+       MSC1 = (MSC1 & ~0xffff) |
+               MSC_NonBrst | MSC_32BitStMem |
+               MSC_RdAcc(2) | MSC_WrAcc(2) | MSC_Rec(0);
 
        if (!machine_has_neponset())
                sa1100_register_uart_fns(&assabet_port_fns);
index 612a45689770752bc9e1319d2eeb430ae36a449c..7fb96ebdc0fbc74d37b1122fe0462026031a8889 100644 (file)
@@ -289,7 +289,7 @@ static void collie_flash_exit(void)
 }
 
 static struct flash_platform_data collie_flash_data = {
-       .map_name       = "cfi_probe",
+       .map_name       = "jedec_probe",
        .init           = collie_flash_init,
        .set_vpp        = collie_set_vpp,
        .exit           = collie_flash_exit,
diff --git a/arch/arm/mach-sa1100/include/mach/gpio.h b/arch/arm/mach-sa1100/include/mach/gpio.h
deleted file mode 100644 (file)
index 6a9eecf..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * arch/arm/mach-sa1100/include/mach/gpio.h
- *
- * SA1100 GPIO wrappers for arch-neutral GPIO calls
- *
- * Written by Philipp Zabel <philipp.zabel@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#ifndef __ASM_ARCH_SA1100_GPIO_H
-#define __ASM_ARCH_SA1100_GPIO_H
-
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm-generic/gpio.h>
-
-#define __ARM_GPIOLIB_COMPLEX
-
-static inline int gpio_get_value(unsigned gpio)
-{
-       if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX))
-               return GPLR & GPIO_GPIO(gpio);
-       else
-               return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-       if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX))
-               if (value)
-                       GPSR = GPIO_GPIO(gpio);
-               else
-                       GPCR = GPIO_GPIO(gpio);
-       else
-               __gpio_set_value(gpio, value);
-}
-
-#define gpio_cansleep  __gpio_cansleep
-
-#endif
index 7d9df16f04a2276ccceba5b8315cf296988a2334..c810620db53d60235916e8ecf25c6402f2b984b1 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef _INCLUDE_H3XXX_H_
 #define _INCLUDE_H3XXX_H_
 
+#include "hardware.h" /* Gives GPIO_MAX */
+
 /* Physical memory regions corresponding to chip selects */
 #define H3600_EGPIO_PHYS       (SA1100_CS5_PHYS + 0x01000000)
 #define H3600_BANK_2_PHYS      SA1100_CS2_PHYS
index 5bd1479d3deb7e98a0d38c3c192abd2824b2825d..7f8f6076d3609e82382bb98f116df3bfc59049ed 100644 (file)
@@ -1108,9 +1108,9 @@ static const struct pinctrl_map eva_pinctrl_map[] = {
        PIN_MAP_MUX_GROUP_DEFAULT("asoc-simple-card.1", "pfc-r8a7740",
                                  "fsib_mclk_in", "fsib"),
        /* GETHER */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh-eth", "pfc-r8a7740",
+       PIN_MAP_MUX_GROUP_DEFAULT("r8a7740-gether", "pfc-r8a7740",
                                  "gether_mii", "gether"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh-eth", "pfc-r8a7740",
+       PIN_MAP_MUX_GROUP_DEFAULT("r8a7740-gether", "pfc-r8a7740",
                                  "gether_int", "gether"),
        /* HDMI */
        PIN_MAP_MUX_GROUP_DEFAULT("sh-mobile-hdmi", "pfc-r8a7740",
index ffb6f0ac760643b79075441fe23f048d69d293c1..5930af8d434fb90c4a79fd8b0f8c225be9b93b58 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_data/gpio-rcar.h>
 #include <linux/platform_device.h>
+#include <linux/phy.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/sh_eth.h>
@@ -155,6 +156,30 @@ static void __init lager_add_standard_devices(void)
                                          &ether_pdata, sizeof(ether_pdata));
 }
 
+/*
+ * Ether LEDs on the Lager board are named LINK and ACTIVE which corresponds
+ * to non-default 01 setting of the Micrel KSZ8041 PHY control register 1 bits
+ * 14-15. We have to set them back to 01 from the default 00 value each time
+ * the PHY is reset. It's also important because the PHY's LED0 signal is
+ * connected to SoC's ETH_LINK signal and in the PHY's default mode it will
+ * bounce on and off after each packet, which we apparently want to avoid.
+ */
+static int lager_ksz8041_fixup(struct phy_device *phydev)
+{
+       u16 phyctrl1 = phy_read(phydev, 0x1e);
+
+       phyctrl1 &= ~0xc000;
+       phyctrl1 |= 0x4000;
+       return phy_write(phydev, 0x1e, phyctrl1);
+}
+
+static void __init lager_init(void)
+{
+       lager_add_standard_devices();
+
+       phy_register_fixup_for_id("r8a7790-ether-ff:01", lager_ksz8041_fixup);
+}
+
 static const char *lager_boards_compat_dt[] __initdata = {
        "renesas,lager",
        NULL,
@@ -163,6 +188,6 @@ static const char *lager_boards_compat_dt[] __initdata = {
 DT_MACHINE_START(LAGER_DT, "lager")
        .init_early     = r8a7790_init_delay,
        .init_time      = r8a7790_timer_init,
-       .init_machine   = lager_add_standard_devices,
+       .init_machine   = lager_init,
        .dt_compat      = lager_boards_compat_dt,
 MACHINE_END
index 8ea5ef6c79ccbed859318cc69745488c0d273290..5bd2e851e3c7f2d03cd7ae4dd647ec1cc7d9c537 100644 (file)
@@ -555,7 +555,7 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("pll2h",                  &pll2h_clk),
 
        /* CPU clock */
-       CLKDEV_DEV_ID("cpufreq-cpu0",           &z_clk),
+       CLKDEV_DEV_ID("cpu0",                   &z_clk),
 
        /* DIV6 */
        CLKDEV_CON_ID("zb",                     &div6_clks[DIV6_ZB]),
index 1942eaef518134804110ed14cc5a61c94550af27..c92c023f0d27c1de8778665e372d1abfba82db42 100644 (file)
@@ -616,7 +616,7 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("smp_twd", &twd_clk), /* smp_twd */
 
        /* DIV4 clocks */
-       CLKDEV_DEV_ID("cpufreq-cpu0", &div4_clks[DIV4_Z]),
+       CLKDEV_DEV_ID("cpu0", &div4_clks[DIV4_Z]),
 
        /* DIV6 clocks */
        CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]),
index a85adcd00882e4ad193cd3b177179a5ad8162e6a..a1659863bfd5cb650338d6d8919ab0b145da1d57 100644 (file)
@@ -1,7 +1,3 @@
-menu "ST-Ericsson AB U300/U335 Platform"
-
-comment "ST-Ericsson Mobile Platform Products"
-
 config ARCH_U300
        bool "ST-Ericsson U300 Series" if ARCH_MULTI_V5
        depends on MMU
@@ -25,7 +21,9 @@ config ARCH_U300
        help
          Support for ST-Ericsson U300 series mobile platforms.
 
-comment "ST-Ericsson U300/U335 Feature Selections"
+if ARCH_U300
+
+menu "ST-Ericsson AB U300/U335 Platform"
 
 config MACH_U300
        depends on ARCH_U300
@@ -53,3 +51,5 @@ config MACH_U300_SPIDUMMY
                SPI framework and ARM PL022 support.
 
 endmenu
+
+endif
index 82ccf1d98735520ef4727c615398e478fccb8b02..264f894c0e3d228ca62280deb0aaec8b350a2fa1 100644 (file)
@@ -69,6 +69,7 @@ static int __init ux500_l2x0_init(void)
         * some SMI service available.
         */
        outer_cache.disable = NULL;
+       outer_cache.set_debug = NULL;
 
        return 0;
 }
index 7aeb5d60e484642d08ed119ecfd083b3c4074a46..e6eb4819291241f30b51d5e7b58c14d1d07c0d32 100644 (file)
@@ -131,6 +131,16 @@ static void tc2_pm_down(u64 residency)
        } else
                BUG();
 
+       /*
+        * If the CPU is committed to power down, make sure
+        * the power controller will be in charge of waking it
+        * up upon IRQ, ie IRQ lines are cut from GIC CPU IF
+        * to the CPU by disabling the GIC CPU IF to prevent wfi
+        * from completing execution behind power controller back
+        */
+       if (!skip_wfi)
+               gic_cpu_if_down();
+
        if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
                arch_spin_unlock(&tc2_pm_lock);
 
@@ -231,7 +241,6 @@ static void tc2_pm_suspend(u64 residency)
        cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
        cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
        ve_spc_set_resume_addr(cluster, cpu, virt_to_phys(mcpm_entry_point));
-       gic_cpu_if_down();
        tc2_pm_down(residency);
 }
 
index f5e1a8471714cd421e2ab9dee54ae88f144316d1..7b3f2426a1fb048cb2422f1887670109d2c2cb92 100644 (file)
@@ -159,7 +159,7 @@ EXPORT_SYMBOL(arm_coherent_dma_ops);
 
 static u64 get_coherent_dma_mask(struct device *dev)
 {
-       u64 mask = (u64)arm_dma_limit;
+       u64 mask = (u64)DMA_BIT_MASK(32);
 
        if (dev) {
                mask = dev->coherent_dma_mask;
@@ -173,10 +173,30 @@ static u64 get_coherent_dma_mask(struct device *dev)
                        return 0;
                }
 
-               if ((~mask) & (u64)arm_dma_limit) {
-                       dev_warn(dev, "coherent DMA mask %#llx is smaller "
-                                "than system GFP_DMA mask %#llx\n",
-                                mask, (u64)arm_dma_limit);
+               /*
+                * If the mask allows for more memory than we can address,
+                * and we actually have that much memory, then fail the
+                * allocation.
+                */
+               if (sizeof(mask) != sizeof(dma_addr_t) &&
+                   mask > (dma_addr_t)~0 &&
+                   dma_to_pfn(dev, ~0) > arm_dma_pfn_limit) {
+                       dev_warn(dev, "Coherent DMA mask %#llx is larger than dma_addr_t allows\n",
+                                mask);
+                       dev_warn(dev, "Driver did not use or check the return value from dma_set_coherent_mask()?\n");
+                       return 0;
+               }
+
+               /*
+                * Now check that the mask, when translated to a PFN,
+                * fits within the allowable addresses which we can
+                * allocate.
+                */
+               if (dma_to_pfn(dev, mask) < arm_dma_pfn_limit) {
+                       dev_warn(dev, "Coherent DMA mask %#llx (pfn %#lx-%#lx) covers a smaller range of system memory than the DMA zone pfn 0x0-%#lx\n",
+                                mask,
+                                dma_to_pfn(dev, 0), dma_to_pfn(dev, mask) + 1,
+                                arm_dma_pfn_limit + 1);
                        return 0;
                }
        }
@@ -1007,8 +1027,27 @@ void arm_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
  */
 int dma_supported(struct device *dev, u64 mask)
 {
-       if (mask < (u64)arm_dma_limit)
+       unsigned long limit;
+
+       /*
+        * If the mask allows for more memory than we can address,
+        * and we actually have that much memory, then we must
+        * indicate that DMA to this device is not supported.
+        */
+       if (sizeof(mask) != sizeof(dma_addr_t) &&
+           mask > (dma_addr_t)~0 &&
+           dma_to_pfn(dev, ~0) > arm_dma_pfn_limit)
+               return 0;
+
+       /*
+        * Translate the device's DMA mask to a PFN limit.  This
+        * PFN number includes the page which we can DMA to.
+        */
+       limit = dma_to_pfn(dev, mask);
+
+       if (limit < arm_dma_pfn_limit)
                return 0;
+
        return 1;
 }
 EXPORT_SYMBOL(dma_supported);
index 83cb3ac27095146f3f60c04047c6b212856a73b2..8e0e52eb76b57d7f9d4208fafbcdf024be369c75 100644 (file)
@@ -10,6 +10,7 @@
 #include <asm/system_info.h>
 
 pgd_t *idmap_pgd;
+phys_addr_t (*arch_virt_to_idmap) (unsigned long x);
 
 #ifdef CONFIG_ARM_LPAE
 static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end,
@@ -67,8 +68,9 @@ static void identity_mapping_add(pgd_t *pgd, const char *text_start,
        unsigned long addr, end;
        unsigned long next;
 
-       addr = virt_to_phys(text_start);
-       end = virt_to_phys(text_end);
+       addr = virt_to_idmap(text_start);
+       end = virt_to_idmap(text_end);
+       pr_info("Setting up static identity map for 0x%lx - 0x%lx\n", addr, end);
 
        prot |= PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF;
 
@@ -90,8 +92,6 @@ static int __init init_static_idmap(void)
        if (!idmap_pgd)
                return -ENOMEM;
 
-       pr_info("Setting up static identity map for 0x%p - 0x%p\n",
-               __idmap_text_start, __idmap_text_end);
        identity_mapping_add(idmap_pgd, __idmap_text_start,
                             __idmap_text_end, 0);
 
index febaee7ca57be76487290a2ac45c6cf74e53759c..d50533c2b409c1c50c8d6e427acd86652f7aa549 100644 (file)
@@ -218,6 +218,7 @@ EXPORT_SYMBOL(arm_dma_zone_size);
  * so a successful GFP_DMA allocation will always satisfy this.
  */
 phys_addr_t arm_dma_limit;
+unsigned long arm_dma_pfn_limit;
 
 static void __init arm_adjust_dma_zone(unsigned long *size, unsigned long *hole,
        unsigned long dma_size)
@@ -240,6 +241,7 @@ void __init setup_dma_zone(const struct machine_desc *mdesc)
                arm_dma_limit = PHYS_OFFSET + arm_dma_zone_size - 1;
        } else
                arm_dma_limit = 0xffffffff;
+       arm_dma_pfn_limit = arm_dma_limit >> PAGE_SHIFT;
 #endif
 }
 
@@ -424,12 +426,10 @@ void __init bootmem_init(void)
         * This doesn't seem to be used by the Linux memory manager any
         * more, but is used by ll_rw_block.  If we can get rid of it, we
         * also get rid of some of the stuff above as well.
-        *
-        * Note: max_low_pfn and max_pfn reflect the number of _pages_ in
-        * the system, not the maximum PFN.
         */
-       max_low_pfn = max_low - PHYS_PFN_OFFSET;
-       max_pfn = max_high - PHYS_PFN_OFFSET;
+       min_low_pfn = min;
+       max_low_pfn = max_low;
+       max_pfn = max_high;
 }
 
 /*
@@ -535,7 +535,7 @@ static inline void free_area_high(unsigned long pfn, unsigned long end)
 static void __init free_highpages(void)
 {
 #ifdef CONFIG_HIGHMEM
-       unsigned long max_low = max_low_pfn + PHYS_PFN_OFFSET;
+       unsigned long max_low = max_low_pfn;
        struct memblock_region *mem, *res;
 
        /* set highmem page free */
index d5a4e9ad8f0f68549947100081e3b9f8ac2e1b3a..d5a982d15a88e2a37a524267f31633f497aa0d4b 100644 (file)
@@ -81,8 +81,10 @@ extern __init void add_static_vm_early(struct static_vm *svm);
 
 #ifdef CONFIG_ZONE_DMA
 extern phys_addr_t arm_dma_limit;
+extern unsigned long arm_dma_pfn_limit;
 #else
 #define arm_dma_limit ((phys_addr_t)~0)
+#define arm_dma_pfn_limit (~0ul >> PAGE_SHIFT)
 #endif
 
 extern phys_addr_t arm_lowmem_limit;
index 0c6356255fe31122f2527a0a2947439e69b0e953..d27158c38eb0b190b869e028b93d8265fb90969e 100644 (file)
@@ -202,13 +202,11 @@ int valid_phys_addr_range(phys_addr_t addr, size_t size)
 }
 
 /*
- * We don't use supersection mappings for mmap() on /dev/mem, which
- * means that we can't map the memory area above the 4G barrier into
- * userspace.
+ * Do not allow /dev/mem mappings beyond the supported physical range.
  */
 int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
 {
-       return !(pfn + (size >> PAGE_SHIFT) > 0x00100000);
+       return (pfn + (size >> PAGE_SHIFT)) <= (1 + (PHYS_MASK >> PAGE_SHIFT));
 }
 
 #ifdef CONFIG_STRICT_DEVMEM
index b1d17eeb59b895cd429e762d082d6c5c56c3ff57..78eeeca78f5ab331707fcd73b4956c503c2d880b 100644 (file)
@@ -28,6 +28,8 @@
 #include <asm/highmem.h>
 #include <asm/system_info.h>
 #include <asm/traps.h>
+#include <asm/procinfo.h>
+#include <asm/memory.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -1315,6 +1317,86 @@ static void __init map_lowmem(void)
        }
 }
 
+#ifdef CONFIG_ARM_LPAE
+/*
+ * early_paging_init() recreates boot time page table setup, allowing machines
+ * to switch over to a high (>4G) address space on LPAE systems
+ */
+void __init early_paging_init(const struct machine_desc *mdesc,
+                             struct proc_info_list *procinfo)
+{
+       pmdval_t pmdprot = procinfo->__cpu_mm_mmu_flags;
+       unsigned long map_start, map_end;
+       pgd_t *pgd0, *pgdk;
+       pud_t *pud0, *pudk, *pud_start;
+       pmd_t *pmd0, *pmdk;
+       phys_addr_t phys;
+       int i;
+
+       if (!(mdesc->init_meminfo))
+               return;
+
+       /* remap kernel code and data */
+       map_start = init_mm.start_code;
+       map_end   = init_mm.brk;
+
+       /* get a handle on things... */
+       pgd0 = pgd_offset_k(0);
+       pud_start = pud0 = pud_offset(pgd0, 0);
+       pmd0 = pmd_offset(pud0, 0);
+
+       pgdk = pgd_offset_k(map_start);
+       pudk = pud_offset(pgdk, map_start);
+       pmdk = pmd_offset(pudk, map_start);
+
+       mdesc->init_meminfo();
+
+       /* Run the patch stub to update the constants */
+       fixup_pv_table(&__pv_table_begin,
+               (&__pv_table_end - &__pv_table_begin) << 2);
+
+       /*
+        * Cache cleaning operations for self-modifying code
+        * We should clean the entries by MVA but running a
+        * for loop over every pv_table entry pointer would
+        * just complicate the code.
+        */
+       flush_cache_louis();
+       dsb();
+       isb();
+
+       /* remap level 1 table */
+       for (i = 0; i < PTRS_PER_PGD; pud0++, i++) {
+               set_pud(pud0,
+                       __pud(__pa(pmd0) | PMD_TYPE_TABLE | L_PGD_SWAPPER));
+               pmd0 += PTRS_PER_PMD;
+       }
+
+       /* remap pmds for kernel mapping */
+       phys = __pa(map_start) & PMD_MASK;
+       do {
+               *pmdk++ = __pmd(phys | pmdprot);
+               phys += PMD_SIZE;
+       } while (phys < map_end);
+
+       flush_cache_all();
+       cpu_switch_mm(pgd0, &init_mm);
+       cpu_set_ttbr(1, __pa(pgd0) + TTBR1_OFFSET);
+       local_flush_bp_all();
+       local_flush_tlb_all();
+}
+
+#else
+
+void __init early_paging_init(const struct machine_desc *mdesc,
+                             struct proc_info_list *procinfo)
+{
+       if (mdesc->init_meminfo)
+               mdesc->init_meminfo();
+}
+
+#endif
+
 /*
  * paging_init() sets up the page tables, initialises the zone memory
  * maps, and sets up the zero page, bad page and bad page tables.
index 1a6bfe954d4926de3a8dcee10fdbe0b0698279b3..835c559786bda923fe0cb8616b3031932a86bb21 100644 (file)
@@ -6,13 +6,6 @@ config FRAME_POINTER
        bool
        default y
 
-config DEBUG_STACK_USAGE
-       bool "Enable stack utilization instrumentation"
-       depends on DEBUG_KERNEL
-       help
-         Enables the display of the minimum amount of free stack which each
-         task has ever had available in the sysrq-T output.
-
 config EARLY_PRINTK
        bool "Early printk support"
        default y
index 5b3e83217b03b1e255c23347fcc4d06859cba9c1..31c81e9b792e21b5078ada9f4299fc55e3071f86 100644 (file)
@@ -42,7 +42,7 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
-# CONFIG_BLK_DEV is not set
+CONFIG_BLK_DEV=y
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
@@ -72,6 +72,7 @@ CONFIG_LOGO=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
 CONFIG_FUSE_FS=y
@@ -90,3 +91,5 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_FTRACE is not set
 CONFIG_ATOMIC64_SELFTEST=y
+CONFIG_VIRTIO_MMIO=y
+CONFIG_VIRTIO_BLK=y
index 6d4482fa35bcbc183bf64d9239a4a5a87bb86705..e2950b098e76f68803559ca264d7bed94ffa4789 100644 (file)
@@ -43,6 +43,6 @@
                                 COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\
                                 COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV)
 
-extern unsigned int elf_hwcap;
+extern unsigned long elf_hwcap;
 #endif
 #endif
index edb3d5c73a3232c35532bd5e489add1cabf7201c..7ecc2b23882e44c62055ba2a57d49833ae119850 100644 (file)
@@ -166,9 +166,10 @@ do {                                                                       \
 
 #define get_user(x, ptr)                                               \
 ({                                                                     \
+       __typeof__(*(ptr)) __user *__p = (ptr);                         \
        might_fault();                                                  \
-       access_ok(VERIFY_READ, (ptr), sizeof(*(ptr))) ?                 \
-               __get_user((x), (ptr)) :                                \
+       access_ok(VERIFY_READ, __p, sizeof(*__p)) ?                     \
+               __get_user((x), __p) :                                  \
                ((x) = 0, -EFAULT);                                     \
 })
 
@@ -227,9 +228,10 @@ do {                                                                       \
 
 #define put_user(x, ptr)                                               \
 ({                                                                     \
+       __typeof__(*(ptr)) __user *__p = (ptr);                         \
        might_fault();                                                  \
-       access_ok(VERIFY_WRITE, (ptr), sizeof(*(ptr))) ?                \
-               __put_user((x), (ptr)) :                                \
+       access_ok(VERIFY_WRITE, __p, sizeof(*__p)) ?                    \
+               __put_user((x), __p) :                                  \
                -EFAULT;                                                \
 })
 
index 1f2e4d5a5c0fd65ec86d5f487256dc7de9c4584e..bb785d23dbde8764d1a53df79ef4a7b96dc48966 100644 (file)
@@ -80,8 +80,10 @@ void fpsimd_thread_switch(struct task_struct *next)
 
 void fpsimd_flush_thread(void)
 {
+       preempt_disable();
        memset(&current->thread.fpsimd_state, 0, sizeof(struct fpsimd_state));
        fpsimd_load_state(&current->thread.fpsimd_state);
+       preempt_enable();
 }
 
 #ifdef CONFIG_KERNEL_MODE_NEON
index 57fb55c44c901c19c7264f02ff44d6c481fadc56..7ae8a1f00c3c82bf256f716aee79aaf24fac8f1b 100644 (file)
@@ -143,15 +143,26 @@ void machine_restart(char *cmd)
 
 void __show_regs(struct pt_regs *regs)
 {
-       int i;
+       int i, top_reg;
+       u64 lr, sp;
+
+       if (compat_user_mode(regs)) {
+               lr = regs->compat_lr;
+               sp = regs->compat_sp;
+               top_reg = 12;
+       } else {
+               lr = regs->regs[30];
+               sp = regs->sp;
+               top_reg = 29;
+       }
 
        show_regs_print_info(KERN_DEFAULT);
        print_symbol("PC is at %s\n", instruction_pointer(regs));
-       print_symbol("LR is at %s\n", regs->regs[30]);
+       print_symbol("LR is at %s\n", lr);
        printk("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n",
-              regs->pc, regs->regs[30], regs->pstate);
-       printk("sp : %016llx\n", regs->sp);
-       for (i = 29; i >= 0; i--) {
+              regs->pc, lr, regs->pstate);
+       printk("sp : %016llx\n", sp);
+       for (i = top_reg; i >= 0; i--) {
                printk("x%-2d: %016llx ", i, regs->regs[i]);
                if (i % 2 == 0)
                        printk("\n");
index 12ad8f3d0cfd32c4f5409a0b8f29b499b7f5cf80..055cfb80e05c5d8d352880cb6db85d2cdea38241 100644 (file)
@@ -57,7 +57,7 @@
 unsigned int processor_id;
 EXPORT_SYMBOL(processor_id);
 
-unsigned int elf_hwcap __read_mostly;
+unsigned long elf_hwcap __read_mostly;
 EXPORT_SYMBOL_GPL(elf_hwcap);
 
 static const char *cpu_name;
index 6d6acf153bffb276b5fa9affd87e48a1cb17a318..c23751b0612033f56533955788eabefa6c5fd39e 100644 (file)
@@ -130,7 +130,7 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
        force_sig_info(sig, &si, tsk);
 }
 
-void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs)
+static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs)
 {
        struct task_struct *tsk = current;
        struct mm_struct *mm = tsk->active_mm;
index 8ae80a18e8ecbf18acd29a0aed49c70d5ecbdbea..19da91e0cd278911ec8400449d199325e528f00b 100644 (file)
@@ -35,7 +35,7 @@
  */
 ENTRY(__cpu_flush_user_tlb_range)
        vma_vm_mm x3, x2                        // get vma->vm_mm
-       mmid    x3, x3                          // get vm_mm->context.id
+       mmid    w3, x3                          // get vm_mm->context.id
        dsb     sy
        lsr     x0, x0, #12                     // align address
        lsr     x1, x1, #12
index d22af851f3f638b09fdc4394a05e2cebf8a10201..fd7980743890b2ebcf5ff9b5ca40fc4ef83de220 100644 (file)
@@ -1,5 +1,19 @@
 
 generic-y      += clkdev.h
+generic-y       += cputime.h
+generic-y       += delay.h
+generic-y       += device.h
+generic-y       += div64.h
+generic-y       += emergency-restart.h
 generic-y      += exec.h
-generic-y      += trace_clock.h
+generic-y       += futex.h
+generic-y       += irq_regs.h
 generic-y      += param.h
+generic-y       += local.h
+generic-y       += local64.h
+generic-y       += percpu.h
+generic-y       += scatterlist.h
+generic-y       += sections.h
+generic-y       += topology.h
+generic-y      += trace_clock.h
+generic-y       += xor.h
diff --git a/arch/avr32/include/asm/cputime.h b/arch/avr32/include/asm/cputime.h
deleted file mode 100644 (file)
index e87e0f8..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_AVR32_CPUTIME_H
-#define __ASM_AVR32_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __ASM_AVR32_CPUTIME_H */
diff --git a/arch/avr32/include/asm/delay.h b/arch/avr32/include/asm/delay.h
deleted file mode 100644 (file)
index 9670e12..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/delay.h>
diff --git a/arch/avr32/include/asm/device.h b/arch/avr32/include/asm/device.h
deleted file mode 100644 (file)
index d8f9872..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
-#include <asm-generic/device.h>
-
diff --git a/arch/avr32/include/asm/div64.h b/arch/avr32/include/asm/div64.h
deleted file mode 100644 (file)
index d7ddd4f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_AVR32_DIV64_H
-#define __ASM_AVR32_DIV64_H
-
-#include <asm-generic/div64.h>
-
-#endif /* __ASM_AVR32_DIV64_H */
diff --git a/arch/avr32/include/asm/emergency-restart.h b/arch/avr32/include/asm/emergency-restart.h
deleted file mode 100644 (file)
index 3e7e014..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_AVR32_EMERGENCY_RESTART_H
-#define __ASM_AVR32_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* __ASM_AVR32_EMERGENCY_RESTART_H */
diff --git a/arch/avr32/include/asm/futex.h b/arch/avr32/include/asm/futex.h
deleted file mode 100644 (file)
index 10419f1..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_AVR32_FUTEX_H
-#define __ASM_AVR32_FUTEX_H
-
-#include <asm-generic/futex.h>
-
-#endif /* __ASM_AVR32_FUTEX_H */
diff --git a/arch/avr32/include/asm/irq_regs.h b/arch/avr32/include/asm/irq_regs.h
deleted file mode 100644 (file)
index 3dd9c0b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff --git a/arch/avr32/include/asm/local.h b/arch/avr32/include/asm/local.h
deleted file mode 100644 (file)
index 1c16196..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_AVR32_LOCAL_H
-#define __ASM_AVR32_LOCAL_H
-
-#include <asm-generic/local.h>
-
-#endif /* __ASM_AVR32_LOCAL_H */
diff --git a/arch/avr32/include/asm/local64.h b/arch/avr32/include/asm/local64.h
deleted file mode 100644 (file)
index 36c93b5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
diff --git a/arch/avr32/include/asm/percpu.h b/arch/avr32/include/asm/percpu.h
deleted file mode 100644 (file)
index 69227b4..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_AVR32_PERCPU_H
-#define __ASM_AVR32_PERCPU_H
-
-#include <asm-generic/percpu.h>
-
-#endif /* __ASM_AVR32_PERCPU_H */
diff --git a/arch/avr32/include/asm/scatterlist.h b/arch/avr32/include/asm/scatterlist.h
deleted file mode 100644 (file)
index a5902d9..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_AVR32_SCATTERLIST_H
-#define __ASM_AVR32_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* __ASM_AVR32_SCATTERLIST_H */
diff --git a/arch/avr32/include/asm/sections.h b/arch/avr32/include/asm/sections.h
deleted file mode 100644 (file)
index aa14252..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_AVR32_SECTIONS_H
-#define __ASM_AVR32_SECTIONS_H
-
-#include <asm-generic/sections.h>
-
-#endif /* __ASM_AVR32_SECTIONS_H */
diff --git a/arch/avr32/include/asm/topology.h b/arch/avr32/include/asm/topology.h
deleted file mode 100644 (file)
index 5b766cb..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_AVR32_TOPOLOGY_H
-#define __ASM_AVR32_TOPOLOGY_H
-
-#include <asm-generic/topology.h>
-
-#endif /* __ASM_AVR32_TOPOLOGY_H */
diff --git a/arch/avr32/include/asm/xor.h b/arch/avr32/include/asm/xor.h
deleted file mode 100644 (file)
index 99c87aa..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_XOR_H
-#define _ASM_XOR_H
-
-#include <asm-generic/xor.h>
-
-#endif
index c2731003edef556c18cd137f4a0b1aac5e770cc3..42a53e740a7ee1c93044a01742e93250dc919346 100644 (file)
@@ -289,7 +289,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
                memset(childregs, 0, sizeof(struct pt_regs));
                p->thread.cpu_context.r0 = arg;
                p->thread.cpu_context.r1 = usp; /* fn */
-               p->thread.cpu_context.r2 = syscall_return;
+               p->thread.cpu_context.r2 = (unsigned long)syscall_return;
                p->thread.cpu_context.pc = (unsigned long)ret_from_kernel_thread;
                childregs->sr = MODE_SUPERVISOR;
        } else {
index 869a1c6ffeee944a64608d996877a78ee3499245..12f828ad5058d09158f8d3e2007b76a7a42cbb4a 100644 (file)
@@ -98,7 +98,14 @@ static void comparator_mode(enum clock_event_mode mode,
        case CLOCK_EVT_MODE_SHUTDOWN:
                sysreg_write(COMPARE, 0);
                pr_debug("%s: stop\n", evdev->name);
-               cpu_idle_poll_ctrl(false);
+               if (evdev->mode == CLOCK_EVT_MODE_ONESHOT ||
+                   evdev->mode == CLOCK_EVT_MODE_RESUME) {
+                       /*
+                        * Only disable idle poll if we have forced that
+                        * in a previous call.
+                        */
+                       cpu_idle_poll_ctrl(false);
+               }
                break;
        default:
                BUG();
index 75a36ad11ff51d0623243ee643b192eb7b9b9b34..ca8f8340d75f535b1cad5c1c8eed14bbc71f9634 100644 (file)
@@ -288,9 +288,6 @@ endif
 vmlinux.32: vmlinux
        $(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@
 
-
-#obj-$(CONFIG_KPROBES)         += kprobes.o
-
 #
 # The 64-bit ELF tools are pretty broken so at this time we generate 64-bit
 # ELF files from 32-bit files by conversion.
index 4a9baa9f63300cab298d913009c3d840d8adbc12..9969dbab19e36e3f2bd1210c93840bc85bfd7f16 100644 (file)
@@ -276,7 +276,7 @@ static struct platform_device mtx1_pci_host = {
        .resource       = alchemy_pci_host_res,
 };
 
-static struct __initdata platform_device * mtx1_devs[] = {
+static struct platform_device *mtx1_devs[] __initdata = {
        &mtx1_pci_host,
        &mtx1_gpio_leds,
        &mtx1_wdt,
index fcc69562611716957cdec6b268ff36dac49f0664..2adc7edda49c931a9930b7c54fbbe6f749f47d7c 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/syscore_ops.h>
+#include <asm/cpu.h>
 #include <asm/mach-au1x00/au1000.h>
 
 /* control register offsets */
@@ -358,7 +359,7 @@ static inline int au1200_coherency_bug(void)
 {
 #if defined(CONFIG_DMA_COHERENT)
        /* Au1200 AB USB does not support coherent memory */
-       if (!(read_c0_prid() & 0xff)) {
+       if (!(read_c0_prid() & PRID_REV_MASK)) {
                printk(KERN_INFO "Au1200 USB: this is chip revision AB !!\n");
                printk(KERN_INFO "Au1200 USB: update your board or re-configure"
                                 " the kernel\n");
index 7e17374a9ae89fc79257b021c464c3a10d2a7f6a..b713cd64b08740f083f2a25026ee063f8ae5cfdd 100644 (file)
@@ -306,14 +306,14 @@ void __init bcm63xx_cpu_init(void)
 
        switch (c->cputype) {
        case CPU_BMIPS3300:
-               if ((read_c0_prid() & 0xff00) != PRID_IMP_BMIPS3300_ALT)
+               if ((read_c0_prid() & PRID_IMP_MASK) != PRID_IMP_BMIPS3300_ALT)
                        __cpu_name[cpu] = "Broadcom BCM6338";
                /* fall-through */
        case CPU_BMIPS32:
                chipid_reg = BCM_6345_PERF_BASE;
                break;
        case CPU_BMIPS4350:
-               switch ((read_c0_prid() & 0xff)) {
+               switch ((read_c0_prid() & PRID_REV_MASK)) {
                case 0x04:
                        chipid_reg = BCM_3368_PERF_BASE;
                        break;
index 68ae3887b3e5e5f2ec62d47d027805801acac2d0..08c00e4972fa54a09a7345dec8b9d35d65b1e6eb 120000 (symlink)
@@ -1 +1 @@
-../../../../../include/dt-bindings
+../../../../../include/dt-bindings
\ No newline at end of file
index 02193953eb9e6ccb56529ee6880027ad92219a04..b752c4ed0b797938c6ff58e7e1583982cdbdd5ac 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/smp.h>
 
 #include <asm/cpu-info.h>
+#include <asm/cpu-type.h>
 #include <asm/time.h>
 
 #include <asm/octeon/octeon.h>
index ab169046e442a9c44a74e2db2fcb2cf14a11081f..468f665de7bb731e5d8cf71dcef5c1461c146e48 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
+#include <asm/cpu-type.h>
 #include <asm/processor.h>
 
 #include <asm/dec/prom.h>
index fa44f3ec530214f5014664cda4611b1a5a027251..d445d060e346ab689a177bf584cfebd5b9dfca51 100644 (file)
 #include <asm/cpu-info.h>
 #include <cpu-feature-overrides.h>
 
-#ifndef current_cpu_type
-#define current_cpu_type()     current_cpu_data.cputype
-#endif
-
-#define boot_cpu_type()                cpu_data[0].cputype
-
 /*
  * SMP assumption: Options of CPU 0 are a superset of all processors.
  * This is true for all known MIPS systems.
 
 /*
  * MIPS32, MIPS64, VR5500, IDT32332, IDT32334 and maybe a few other
- * pre-MIPS32/MIPS53 processors have CLO, CLZ. The IDT RC64574 is 64-bit and
+ * pre-MIPS32/MIPS64 processors have CLO, CLZ. The IDT RC64574 is 64-bit and
  * has CLO and CLZ but not DCLO nor DCLZ.  For 64-bit kernels
  * cpu_has_clo_clz also indicates the availability of DCLO and DCLZ.
  */
index 41401d8eb7d1a3ca13bfbe77c7d78575307e3531..21c8e29c8f91e87486f90d3aaa7fbe79220add5b 100644 (file)
@@ -84,6 +84,7 @@ struct cpuinfo_mips {
 extern struct cpuinfo_mips cpu_data[];
 #define current_cpu_data cpu_data[smp_processor_id()]
 #define raw_current_cpu_data cpu_data[raw_smp_processor_id()]
+#define boot_cpu_data cpu_data[0]
 
 extern void cpu_probe(void);
 extern void cpu_report(void);
diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h
new file mode 100644 (file)
index 0000000..4a402cc
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003, 2004 Ralf Baechle
+ * Copyright (C) 2004  Maciej W. Rozycki
+ */
+#ifndef __ASM_CPU_TYPE_H
+#define __ASM_CPU_TYPE_H
+
+#include <linux/smp.h>
+#include <linux/compiler.h>
+
+static inline int __pure __get_cpu_type(const int cpu_type)
+{
+       switch (cpu_type) {
+#if defined(CONFIG_SYS_HAS_CPU_LOONGSON2E) || \
+    defined(CONFIG_SYS_HAS_CPU_LOONGSON2F)
+       case CPU_LOONGSON2:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_LOONGSON1B
+       case CPU_LOONGSON1:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_MIPS32_R1
+       case CPU_4KC:
+       case CPU_ALCHEMY:
+       case CPU_BMIPS3300:
+       case CPU_BMIPS4350:
+       case CPU_PR4450:
+       case CPU_BMIPS32:
+       case CPU_JZRISC:
+#endif
+
+#if defined(CONFIG_SYS_HAS_CPU_MIPS32_R1) || \
+    defined(CONFIG_SYS_HAS_CPU_MIPS32_R2)
+       case CPU_4KEC:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_MIPS32_R2
+       case CPU_4KSC:
+       case CPU_24K:
+       case CPU_34K:
+       case CPU_1004K:
+       case CPU_74K:
+       case CPU_M14KC:
+       case CPU_M14KEC:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_MIPS64_R1
+       case CPU_5KC:
+       case CPU_5KE:
+       case CPU_20KC:
+       case CPU_25KF:
+       case CPU_SB1:
+       case CPU_SB1A:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_MIPS64_R2
+       /*
+        * All MIPS64 R2 processors have their own special symbols.  That is,
+        * there currently is no pure R2 core
+        */
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_R3000
+       case CPU_R2000:
+       case CPU_R3000:
+       case CPU_R3000A:
+       case CPU_R3041:
+       case CPU_R3051:
+       case CPU_R3052:
+       case CPU_R3081:
+       case CPU_R3081E:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_TX39XX
+       case CPU_TX3912:
+       case CPU_TX3922:
+       case CPU_TX3927:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_VR41XX
+       case CPU_VR41XX:
+       case CPU_VR4111:
+       case CPU_VR4121:
+       case CPU_VR4122:
+       case CPU_VR4131:
+       case CPU_VR4133:
+       case CPU_VR4181:
+       case CPU_VR4181A:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_R4300
+       case CPU_R4300:
+       case CPU_R4310:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_R4X00
+       case CPU_R4000PC:
+       case CPU_R4000SC:
+       case CPU_R4000MC:
+       case CPU_R4200:
+       case CPU_R4400PC:
+       case CPU_R4400SC:
+       case CPU_R4400MC:
+       case CPU_R4600:
+       case CPU_R4700:
+       case CPU_R4640:
+       case CPU_R4650:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_TX49XX
+       case CPU_TX49XX:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_R5000
+       case CPU_R5000:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_R5432
+       case CPU_R5432:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_R5500
+       case CPU_R5500:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_R6000
+       case CPU_R6000:
+       case CPU_R6000A:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_NEVADA
+       case CPU_NEVADA:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_R8000
+       case CPU_R8000:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_R10000
+       case CPU_R10000:
+       case CPU_R12000:
+       case CPU_R14000:
+#endif
+#ifdef CONFIG_SYS_HAS_CPU_RM7000
+       case CPU_RM7000:
+       case CPU_SR71000:
+#endif
+#ifdef CONFIG_SYS_HAS_CPU_RM9000
+       case CPU_RM9000:
+#endif
+#ifdef CONFIG_SYS_HAS_CPU_SB1
+       case CPU_SB1:
+       case CPU_SB1A:
+#endif
+#ifdef CONFIG_SYS_HAS_CPU_CAVIUM_OCTEON
+       case CPU_CAVIUM_OCTEON:
+       case CPU_CAVIUM_OCTEON_PLUS:
+       case CPU_CAVIUM_OCTEON2:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_BMIPS4380
+       case CPU_BMIPS4380:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_BMIPS5000
+       case CPU_BMIPS5000:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_XLP
+       case CPU_XLP:
+#endif
+
+#ifdef CONFIG_SYS_HAS_CPU_XLR
+       case CPU_XLR:
+#endif
+               break;
+       default:
+               unreachable();
+       }
+
+       return cpu_type;
+}
+
+static inline int __pure current_cpu_type(void)
+{
+       const int cpu_type = current_cpu_data.cputype;
+
+       return __get_cpu_type(cpu_type);
+}
+
+static inline int __pure boot_cpu_type(void)
+{
+       const int cpu_type = cpu_data[0].cputype;
+
+       return __get_cpu_type(cpu_type);
+}
+
+#endif /* __ASM_CPU_TYPE_H */
index 71b9f1998be7b31b9b7ba0bbd0067f1364c9f8bf..d2035e16502a7d98cfe3e015f9855da2617308f2 100644 (file)
@@ -3,15 +3,14 @@
  *       various MIPS cpu types.
  *
  * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
- * Copyright (C) 2004  Maciej W. Rozycki
+ * Copyright (C) 2004, 2013  Maciej W. Rozycki
  */
 #ifndef _ASM_CPU_H
 #define _ASM_CPU_H
 
-/* Assigned Company values for bits 23:16 of the PRId Register
-   (CP0 register 15, select 0).         As of the MIPS32 and MIPS64 specs from
-   MTI, the PRId register is defined in this (backwards compatible)
-   way:
+/*
+   As of the MIPS32 and MIPS64 specs from MTI, the PRId register (CP0
+   register 15, select 0) is defined in this (backwards compatible) way:
 
   +----------------+----------------+----------------+----------------+
   | Company Options| Company ID            | Processor ID   | Revision       |
    spec.
 */
 
+#define PRID_OPT_MASK          0xff000000
+
+/*
+ * Assigned Company values for bits 23:16 of the PRId register.
+ */
+
+#define PRID_COMP_MASK         0xff0000
+
 #define PRID_COMP_LEGACY       0x000000
 #define PRID_COMP_MIPS         0x010000
 #define PRID_COMP_BROADCOM     0x020000
 #define PRID_COMP_INGENIC      0xd00000
 
 /*
- * Assigned values for the product ID register.         In order to detect a
- * certain CPU type exactly eventually additional registers may need to
- * be examined.         These are valid when 23:16 == PRID_COMP_LEGACY
+ * Assigned Processor ID (implementation) values for bits 15:8 of the PRId
+ * register.  In order to detect a certain CPU type exactly eventually
+ * additional registers may need to be examined.
  */
+
+#define PRID_IMP_MASK          0xff00
+
+/*
+ * These are valid when 23:16 == PRID_COMP_LEGACY
+ */
+
 #define PRID_IMP_R2000         0x0100
 #define PRID_IMP_AU1_REV1      0x0100
 #define PRID_IMP_AU1_REV2      0x0200
 #define PRID_IMP_NETLOGIC_XLP2XX       0x1200
 
 /*
- * Definitions for 7:0 on legacy processors
+ * Particular Revision values for bits 7:0 of the PRId register.
  */
 
 #define PRID_REV_MASK          0x00ff
 
+/*
+ * Definitions for 7:0 on legacy processors
+ */
+
 #define PRID_REV_TX4927                0x0022
 #define PRID_REV_TX4937                0x0030
 #define PRID_REV_R4400         0x0040
  *  31                            16 15             8 7              0
  */
 
+#define FPIR_IMP_MASK          0xff00
+
 #define FPIR_IMP_NONE          0x0000
 
 enum cpu_type_enum {
index 3e11a468cdf83de964bba1d718adfc49222da395..54f9e84db8ac14a0c1ac2cb57077ec4fb231aa21 100644 (file)
@@ -43,6 +43,8 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 
+#include <asm/cpu.h>
+
 /* cpu pipeline flush */
 void static inline au_sync(void)
 {
@@ -140,7 +142,7 @@ static inline int au1xxx_cpu_needs_config_od(void)
 
 static inline int alchemy_get_cputype(void)
 {
-       switch (read_c0_prid() & 0xffff0000) {
+       switch (read_c0_prid() & (PRID_OPT_MASK | PRID_COMP_MASK)) {
        case 0x00030000:
                return ALCHEMY_CPU_AU1000;
                break;
index f4caacd255528ef1a0bc86f0cf2a522a9243e470..1bcb6421205e3d92913a93f7dcdb04c726c0f447 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef __ASM_MACH_IP22_CPU_FEATURE_OVERRIDES_H
 #define __ASM_MACH_IP22_CPU_FEATURE_OVERRIDES_H
 
+#include <asm/cpu.h>
+
 /*
  * IP22 with a variety of processors so we can't use defaults for everything.
  */
index 1d2b6ff60d339ccc8ebdd80b7e374f201a2b6e4f..d6111aa2e8864f0a9452a4a08e178255aca12e94 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef __ASM_MACH_IP27_CPU_FEATURE_OVERRIDES_H
 #define __ASM_MACH_IP27_CPU_FEATURE_OVERRIDES_H
 
+#include <asm/cpu.h>
+
 /*
  * IP27 only comes with R10000 family processors all using the same config
  */
index 65e9c856390d9d43fcf24f7d7c301c4dea665a74..4cec06d133db238b785816bb9c0488e7caf3cd15 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef __ASM_MACH_IP28_CPU_FEATURE_OVERRIDES_H
 #define __ASM_MACH_IP28_CPU_FEATURE_OVERRIDES_H
 
+#include <asm/cpu.h>
+
 /*
  * IP28 only comes with R10000 family processors all using the same config
  */
index fed1c3e9b486b7bf044f66cdedf9e2a1c302c80c..e0331414c7d60f05cab6dc1c40788d513d71da23 100644 (file)
 #define MIPS_CONF4_MMUEXTDEF   (_ULCAST_(3) << 14)
 #define MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT (_ULCAST_(1) << 14)
 
+#define MIPS_CONF5_NF          (_ULCAST_(1) << 0)
+#define MIPS_CONF5_UFR         (_ULCAST_(1) << 2)
+#define MIPS_CONF5_MSAEN       (_ULCAST_(1) << 27)
+#define MIPS_CONF5_EVA         (_ULCAST_(1) << 28)
+#define MIPS_CONF5_CV          (_ULCAST_(1) << 29)
+#define MIPS_CONF5_K           (_ULCAST_(1) << 30)
+
 #define MIPS_CONF6_SYND                (_ULCAST_(1) << 13)
 
 #define MIPS_CONF7_WII         (_ULCAST_(1) << 31)
index f194c08bd057b58393f37a3ce149eab1a282617f..12d6842962bedc8987a689eeff86aea8e5761a10 100644 (file)
@@ -83,6 +83,18 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
 extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
        enum pci_mmap_state mmap_state, int write_combine);
 
+#define HAVE_ARCH_PCI_RESOURCE_TO_USER
+
+static inline void pci_resource_to_user(const struct pci_dev *dev, int bar,
+               const struct resource *rsrc, resource_size_t *start,
+               resource_size_t *end)
+{
+       phys_t size = resource_size(rsrc);
+
+       *start = fixup_bigphys_addr(rsrc->start, size);
+       *end = rsrc->start + size;
+}
+
 /*
  * Dynamic DMA mapping stuff.
  * MIPS has everything mapped statically.
index 6529704aa73ae0c3cee7789648fb5328b3948168..c5424757da6568dcad750863d7ecabcd312ec08d 100644 (file)
@@ -10,7 +10,9 @@
 
 #ifdef __KERNEL__
 
+#include <asm/cpu-features.h>
 #include <asm/mipsregs.h>
+#include <asm/cpu-type.h>
 
 /*
  * This is the clock rate of the i8253 PIT.  A MIPS system may not have
 
 typedef unsigned int cycles_t;
 
+/*
+ * On R4000/R4400 before version 5.0 an erratum exists such that if the
+ * cycle counter is read in the exact moment that it is matching the
+ * compare register, no interrupt will be generated.
+ *
+ * There is a suggested workaround and also the erratum can't strike if
+ * the compare interrupt isn't being used as the clock source device.
+ * However for now the implementaton of this function doesn't get these
+ * fine details right.
+ */
 static inline cycles_t get_cycles(void)
 {
-       return 0;
+       switch (boot_cpu_type()) {
+       case CPU_R4400PC:
+       case CPU_R4400SC:
+       case CPU_R4400MC:
+               if ((read_c0_prid() & 0xff) >= 0x0050)
+                       return read_c0_count();
+               break;
+
+        case CPU_R4000PC:
+        case CPU_R4000SC:
+        case CPU_R4000MC:
+               break;
+
+       default:
+               if (cpu_has_counter)
+                       return read_c0_count();
+               break;
+       }
+
+       return 0;       /* no usable counter */
 }
 
 #endif /* __KERNEL__ */
index f4cff7e4fa8a2a531a80e2374eb4056c46dab7aa..f82c83749a089bf26d5a06846ebd73edcc4130a8 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef _ASM_VGA_H
 #define _ASM_VGA_H
 
+#include <asm/addrspace.h>
 #include <asm/byteorder.h>
 
 /*
@@ -13,7 +14,7 @@
  *     access the videoram directly without any black magic.
  */
 
-#define VGA_MAP_MEM(x, s)      (0xb0000000L + (unsigned long)(x))
+#define VGA_MAP_MEM(x, s)      CKSEG1ADDR(0x10000000L + (unsigned long)(x))
 
 #define vga_readb(x)   (*(x))
 #define vga_writeb(x, y)       (*(y) = (x))
index 37663c7862a5c22e5215bfed85a1187aaefbe1a8..5465dc183e5ac4d26e36d300b1df36fb4cf4d2b5 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <asm/bugs.h>
 #include <asm/cpu.h>
+#include <asm/cpu-type.h>
 #include <asm/fpu.h>
 #include <asm/mipsregs.h>
 #include <asm/watch.h>
@@ -55,7 +56,7 @@ static inline void check_errata(void)
 {
        struct cpuinfo_mips *c = &current_cpu_data;
 
-       switch (c->cputype) {
+       switch (current_cpu_type()) {
        case CPU_34K:
                /*
                 * Erratum "RPS May Cause Incorrect Instruction Execution"
@@ -122,7 +123,7 @@ static inline unsigned long cpu_get_fpu_id(void)
  */
 static inline int __cpu_has_fpu(void)
 {
-       return ((cpu_get_fpu_id() & 0xff00) != FPIR_IMP_NONE);
+       return ((cpu_get_fpu_id() & FPIR_IMP_MASK) != FPIR_IMP_NONE);
 }
 
 static inline void cpu_probe_vmbits(struct cpuinfo_mips *c)
@@ -290,6 +291,17 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c)
        return config4 & MIPS_CONF_M;
 }
 
+static inline unsigned int decode_config5(struct cpuinfo_mips *c)
+{
+       unsigned int config5;
+
+       config5 = read_c0_config5();
+       config5 &= ~MIPS_CONF5_UFR;
+       write_c0_config5(config5);
+
+       return config5 & MIPS_CONF_M;
+}
+
 static void decode_configs(struct cpuinfo_mips *c)
 {
        int ok;
@@ -310,6 +322,8 @@ static void decode_configs(struct cpuinfo_mips *c)
                ok = decode_config3(c);
        if (ok)
                ok = decode_config4(c);
+       if (ok)
+               ok = decode_config5(c);
 
        mips_probe_watch_registers(c);
 
@@ -322,7 +336,7 @@ static void decode_configs(struct cpuinfo_mips *c)
 
 static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
 {
-       switch (c->processor_id & 0xff00) {
+       switch (c->processor_id & PRID_IMP_MASK) {
        case PRID_IMP_R2000:
                c->cputype = CPU_R2000;
                __cpu_name[cpu] = "R2000";
@@ -333,7 +347,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
                c->tlbsize = 64;
                break;
        case PRID_IMP_R3000:
-               if ((c->processor_id & 0xff) == PRID_REV_R3000A) {
+               if ((c->processor_id & PRID_REV_MASK) == PRID_REV_R3000A) {
                        if (cpu_has_confreg()) {
                                c->cputype = CPU_R3081E;
                                __cpu_name[cpu] = "R3081";
@@ -353,7 +367,8 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
                break;
        case PRID_IMP_R4000:
                if (read_c0_config() & CONF_SC) {
-                       if ((c->processor_id & 0xff) >= PRID_REV_R4400) {
+                       if ((c->processor_id & PRID_REV_MASK) >=
+                           PRID_REV_R4400) {
                                c->cputype = CPU_R4400PC;
                                __cpu_name[cpu] = "R4400PC";
                        } else {
@@ -361,7 +376,8 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
                                __cpu_name[cpu] = "R4000PC";
                        }
                } else {
-                       if ((c->processor_id & 0xff) >= PRID_REV_R4400) {
+                       if ((c->processor_id & PRID_REV_MASK) >=
+                           PRID_REV_R4400) {
                                c->cputype = CPU_R4400SC;
                                __cpu_name[cpu] = "R4400SC";
                        } else {
@@ -454,7 +470,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
                        __cpu_name[cpu] = "TX3927";
                        c->tlbsize = 64;
                } else {
-                       switch (c->processor_id & 0xff) {
+                       switch (c->processor_id & PRID_REV_MASK) {
                        case PRID_REV_TX3912:
                                c->cputype = CPU_TX3912;
                                __cpu_name[cpu] = "TX3912";
@@ -640,7 +656,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
 static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
 {
        decode_configs(c);
-       switch (c->processor_id & 0xff00) {
+       switch (c->processor_id & PRID_IMP_MASK) {
        case PRID_IMP_4KC:
                c->cputype = CPU_4KC;
                __cpu_name[cpu] = "MIPS 4Kc";
@@ -711,7 +727,7 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
 static inline void cpu_probe_alchemy(struct cpuinfo_mips *c, unsigned int cpu)
 {
        decode_configs(c);
-       switch (c->processor_id & 0xff00) {
+       switch (c->processor_id & PRID_IMP_MASK) {
        case PRID_IMP_AU1_REV1:
        case PRID_IMP_AU1_REV2:
                c->cputype = CPU_ALCHEMY;
@@ -730,7 +746,7 @@ static inline void cpu_probe_alchemy(struct cpuinfo_mips *c, unsigned int cpu)
                        break;
                case 4:
                        __cpu_name[cpu] = "Au1200";
-                       if ((c->processor_id & 0xff) == 2)
+                       if ((c->processor_id & PRID_REV_MASK) == 2)
                                __cpu_name[cpu] = "Au1250";
                        break;
                case 5:
@@ -748,12 +764,12 @@ static inline void cpu_probe_sibyte(struct cpuinfo_mips *c, unsigned int cpu)
 {
        decode_configs(c);
 
-       switch (c->processor_id & 0xff00) {
+       switch (c->processor_id & PRID_IMP_MASK) {
        case PRID_IMP_SB1:
                c->cputype = CPU_SB1;
                __cpu_name[cpu] = "SiByte SB1";
                /* FPU in pass1 is known to have issues. */
-               if ((c->processor_id & 0xff) < 0x02)
+               if ((c->processor_id & PRID_REV_MASK) < 0x02)
                        c->options &= ~(MIPS_CPU_FPU | MIPS_CPU_32FPR);
                break;
        case PRID_IMP_SB1A:
@@ -766,7 +782,7 @@ static inline void cpu_probe_sibyte(struct cpuinfo_mips *c, unsigned int cpu)
 static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c, unsigned int cpu)
 {
        decode_configs(c);
-       switch (c->processor_id & 0xff00) {
+       switch (c->processor_id & PRID_IMP_MASK) {
        case PRID_IMP_SR71000:
                c->cputype = CPU_SR71000;
                __cpu_name[cpu] = "Sandcraft SR71000";
@@ -779,7 +795,7 @@ static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c, unsigned int cpu)
 static inline void cpu_probe_nxp(struct cpuinfo_mips *c, unsigned int cpu)
 {
        decode_configs(c);
-       switch (c->processor_id & 0xff00) {
+       switch (c->processor_id & PRID_IMP_MASK) {
        case PRID_IMP_PR4450:
                c->cputype = CPU_PR4450;
                __cpu_name[cpu] = "Philips PR4450";
@@ -791,7 +807,7 @@ static inline void cpu_probe_nxp(struct cpuinfo_mips *c, unsigned int cpu)
 static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
 {
        decode_configs(c);
-       switch (c->processor_id & 0xff00) {
+       switch (c->processor_id & PRID_IMP_MASK) {
        case PRID_IMP_BMIPS32_REV4:
        case PRID_IMP_BMIPS32_REV8:
                c->cputype = CPU_BMIPS32;
@@ -806,7 +822,7 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
                set_elf_platform(cpu, "bmips3300");
                break;
        case PRID_IMP_BMIPS43XX: {
-               int rev = c->processor_id & 0xff;
+               int rev = c->processor_id & PRID_REV_MASK;
 
                if (rev >= PRID_REV_BMIPS4380_LO &&
                                rev <= PRID_REV_BMIPS4380_HI) {
@@ -832,7 +848,7 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
 static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu)
 {
        decode_configs(c);
-       switch (c->processor_id & 0xff00) {
+       switch (c->processor_id & PRID_IMP_MASK) {
        case PRID_IMP_CAVIUM_CN38XX:
        case PRID_IMP_CAVIUM_CN31XX:
        case PRID_IMP_CAVIUM_CN30XX:
@@ -875,7 +891,7 @@ static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu)
        decode_configs(c);
        /* JZRISC does not implement the CP0 counter. */
        c->options &= ~MIPS_CPU_COUNTER;
-       switch (c->processor_id & 0xff00) {
+       switch (c->processor_id & PRID_IMP_MASK) {
        case PRID_IMP_JZRISC:
                c->cputype = CPU_JZRISC;
                __cpu_name[cpu] = "Ingenic JZRISC";
@@ -890,7 +906,7 @@ static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu)
 {
        decode_configs(c);
 
-       if ((c->processor_id & 0xff00) == PRID_IMP_NETLOGIC_AU13XX) {
+       if ((c->processor_id & PRID_IMP_MASK) == PRID_IMP_NETLOGIC_AU13XX) {
                c->cputype = CPU_ALCHEMY;
                __cpu_name[cpu] = "Au1300";
                /* following stuff is not for Alchemy */
@@ -905,7 +921,7 @@ static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu)
                        MIPS_CPU_EJTAG   |
                        MIPS_CPU_LLSC);
 
-       switch (c->processor_id & 0xff00) {
+       switch (c->processor_id & PRID_IMP_MASK) {
        case PRID_IMP_NETLOGIC_XLP2XX:
                c->cputype = CPU_XLP;
                __cpu_name[cpu] = "Broadcom XLPII";
@@ -984,7 +1000,7 @@ void cpu_probe(void)
        c->cputype      = CPU_UNKNOWN;
 
        c->processor_id = read_c0_prid();
-       switch (c->processor_id & 0xff0000) {
+       switch (c->processor_id & PRID_COMP_MASK) {
        case PRID_COMP_LEGACY:
                cpu_probe_legacy(c, cpu);
                break;
index 42f8875d244444fb65f79592df7a6e4514a84e9d..f7991d95bff9a67374501ee4b3ce5f3c25973742 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/sched.h>
 #include <asm/cpu.h>
 #include <asm/cpu-info.h>
+#include <asm/cpu-type.h>
 #include <asm/idle.h>
 #include <asm/mipsregs.h>
 
@@ -136,7 +137,7 @@ void __init check_wait(void)
                return;
        }
 
-       switch (c->cputype) {
+       switch (current_cpu_type()) {
        case CPU_R3081:
        case CPU_R3081E:
                cpu_wait = r3081_wait;
index 364d26ae42152ea89f60e5fa18b653daed803e17..dcb8e5d3bb8a11d603e8829cc88739215206ca7b 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/export.h>
 
 #include <asm/cpu-features.h>
+#include <asm/cpu-type.h>
 #include <asm/div64.h>
 #include <asm/smtc_ipi.h>
 #include <asm/time.h>
index aec3408edd4b9c52d6d1b69bc68ac60368e60b48..524841f0280370600966d20f38b41d0eefdb4744 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/break.h>
 #include <asm/cop2.h>
 #include <asm/cpu.h>
+#include <asm/cpu-type.h>
 #include <asm/dsp.h>
 #include <asm/fpu.h>
 #include <asm/fpu_emulator.h>
@@ -622,7 +623,7 @@ static int simulate_rdhwr(struct pt_regs *regs, int rd, int rt)
                regs->regs[rt] = read_c0_count();
                return 0;
        case 3:         /* Count register resolution */
-               switch (current_cpu_data.cputype) {
+               switch (current_cpu_type()) {
                case CPU_20KC:
                case CPU_25KF:
                        regs->regs[rt] = 1;
index 729e7702b1de86212653cf56b49662aa0637c1d9..c8efdb5b6ee0297df1799fe41a3ca94750688119 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/bootinfo.h>
 #include <asm/cacheops.h>
 #include <asm/cpu-features.h>
+#include <asm/cpu-type.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/r4kcache.h>
@@ -186,9 +187,10 @@ static void probe_octeon(void)
        unsigned long dcache_size;
        unsigned int config1;
        struct cpuinfo_mips *c = &current_cpu_data;
+       int cputype = current_cpu_type();
 
        config1 = read_c0_config1();
-       switch (c->cputype) {
+       switch (cputype) {
        case CPU_CAVIUM_OCTEON:
        case CPU_CAVIUM_OCTEON_PLUS:
                c->icache.linesz = 2 << ((config1 >> 19) & 7);
@@ -199,7 +201,7 @@ static void probe_octeon(void)
                        c->icache.sets * c->icache.ways * c->icache.linesz;
                c->icache.waybit = ffs(icache_size / c->icache.ways) - 1;
                c->dcache.linesz = 128;
-               if (c->cputype == CPU_CAVIUM_OCTEON_PLUS)
+               if (cputype == CPU_CAVIUM_OCTEON_PLUS)
                        c->dcache.sets = 2; /* CN5XXX has two Dcache sets */
                else
                        c->dcache.sets = 1; /* CN3XXX has one Dcache set */
index f749f687ee87796e118a13d9807a917b54549d69..bc6f96fcb529d53d16a04b09754a9e4395fd457f 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/highmem.h>
 #include <linux/kernel.h>
 #include <linux/linkage.h>
+#include <linux/preempt.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/mm.h>
@@ -24,6 +25,7 @@
 #include <asm/cacheops.h>
 #include <asm/cpu.h>
 #include <asm/cpu-features.h>
+#include <asm/cpu-type.h>
 #include <asm/io.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -601,11 +603,13 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
        /* Catch bad driver code */
        BUG_ON(size == 0);
 
+       preempt_disable();
        if (cpu_has_inclusive_pcaches) {
                if (size >= scache_size)
                        r4k_blast_scache();
                else
                        blast_scache_range(addr, addr + size);
+               preempt_enable();
                __sync();
                return;
        }
@@ -621,6 +625,7 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
                R4600_HIT_CACHEOP_WAR_IMPL;
                blast_dcache_range(addr, addr + size);
        }
+       preempt_enable();
 
        bc_wback_inv(addr, size);
        __sync();
@@ -631,6 +636,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
        /* Catch bad driver code */
        BUG_ON(size == 0);
 
+       preempt_disable();
        if (cpu_has_inclusive_pcaches) {
                if (size >= scache_size)
                        r4k_blast_scache();
@@ -645,6 +651,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
                         */
                        blast_inv_scache_range(addr, addr + size);
                }
+               preempt_enable();
                __sync();
                return;
        }
@@ -655,6 +662,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
                R4600_HIT_CACHEOP_WAR_IMPL;
                blast_inv_dcache_range(addr, addr + size);
        }
+       preempt_enable();
 
        bc_inv(addr, size);
        __sync();
@@ -780,20 +788,30 @@ static inline void rm7k_erratum31(void)
 
 static inline void alias_74k_erratum(struct cpuinfo_mips *c)
 {
+       unsigned int imp = c->processor_id & PRID_IMP_MASK;
+       unsigned int rev = c->processor_id & PRID_REV_MASK;
+
        /*
         * Early versions of the 74K do not update the cache tags on a
         * vtag miss/ptag hit which can occur in the case of KSEG0/KUSEG
         * aliases. In this case it is better to treat the cache as always
         * having aliases.
         */
-       if ((c->processor_id & 0xff) <= PRID_REV_ENCODE_332(2, 4, 0))
-               c->dcache.flags |= MIPS_CACHE_VTAG;
-       if ((c->processor_id & 0xff) == PRID_REV_ENCODE_332(2, 4, 0))
-               write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND);
-       if (((c->processor_id & 0xff00) == PRID_IMP_1074K) &&
-           ((c->processor_id & 0xff) <= PRID_REV_ENCODE_332(1, 1, 0))) {
-               c->dcache.flags |= MIPS_CACHE_VTAG;
-               write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND);
+       switch (imp) {
+       case PRID_IMP_74K:
+               if (rev <= PRID_REV_ENCODE_332(2, 4, 0))
+                       c->dcache.flags |= MIPS_CACHE_VTAG;
+               if (rev == PRID_REV_ENCODE_332(2, 4, 0))
+                       write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND);
+               break;
+       case PRID_IMP_1074K:
+               if (rev <= PRID_REV_ENCODE_332(1, 1, 0)) {
+                       c->dcache.flags |= MIPS_CACHE_VTAG;
+                       write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND);
+               }
+               break;
+       default:
+               BUG();
        }
 }
 
@@ -809,7 +827,7 @@ static void probe_pcache(void)
        unsigned long config1;
        unsigned int lsize;
 
-       switch (c->cputype) {
+       switch (current_cpu_type()) {
        case CPU_R4600:                 /* QED style two way caches? */
        case CPU_R4700:
        case CPU_R5000:
@@ -1025,7 +1043,8 @@ static void probe_pcache(void)
         * presumably no vendor is shipping his hardware in the "bad"
         * configuration.
         */
-       if ((prid & 0xff00) == PRID_IMP_R4000 && (prid & 0xff) < 0x40 &&
+       if ((prid & PRID_IMP_MASK) == PRID_IMP_R4000 &&
+           (prid & PRID_REV_MASK) < PRID_REV_R4400 &&
            !(config & CONF_SC) && c->icache.linesz != 16 &&
            PAGE_SIZE <= 0x8000)
                panic("Improper R4000SC processor configuration detected");
@@ -1045,7 +1064,7 @@ static void probe_pcache(void)
         * normally they'd suffer from aliases but magic in the hardware deals
         * with that for us so we don't need to take care ourselves.
         */
-       switch (c->cputype) {
+       switch (current_cpu_type()) {
        case CPU_20KC:
        case CPU_25KF:
        case CPU_SB1:
@@ -1065,7 +1084,7 @@ static void probe_pcache(void)
        case CPU_34K:
        case CPU_74K:
        case CPU_1004K:
-               if (c->cputype == CPU_74K)
+               if (current_cpu_type() == CPU_74K)
                        alias_74k_erratum(c);
                if ((read_c0_config7() & (1 << 16))) {
                        /* effectively physically indexed dcache,
@@ -1078,7 +1097,7 @@ static void probe_pcache(void)
                        c->dcache.flags |= MIPS_CACHE_ALIASES;
        }
 
-       switch (c->cputype) {
+       switch (current_cpu_type()) {
        case CPU_20KC:
                /*
                 * Some older 20Kc chips doesn't have the 'VI' bit in
@@ -1207,7 +1226,7 @@ static void setup_scache(void)
         * processors don't have a S-cache that would be relevant to the
         * Linux memory management.
         */
-       switch (c->cputype) {
+       switch (current_cpu_type()) {
        case CPU_R4000SC:
        case CPU_R4000MC:
        case CPU_R4400SC:
@@ -1384,9 +1403,8 @@ static void r4k_cache_error_setup(void)
 {
        extern char __weak except_vec2_generic;
        extern char __weak except_vec2_sb1;
-       struct cpuinfo_mips *c = &current_cpu_data;
 
-       switch (c->cputype) {
+       switch (current_cpu_type()) {
        case CPU_SB1:
        case CPU_SB1A:
                set_uncached_handler(0x100, &except_vec2_sb1, 0x80);
index 664e523653d03a4123b69f9d928fb605d2ca4e8d..5f8b955125801935f33370559476ca93f640c4df 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/highmem.h>
 
 #include <asm/cache.h>
+#include <asm/cpu-type.h>
 #include <asm/io.h>
 
 #include <dma-coherence.h>
@@ -307,12 +308,10 @@ static void mips_dma_sync_sg_for_cpu(struct device *dev,
 {
        int i;
 
-       /* Make sure that gcc doesn't leave the empty loop body.  */
-       for (i = 0; i < nelems; i++, sg++) {
-               if (cpu_needs_post_dma_flush(dev))
+       if (cpu_needs_post_dma_flush(dev))
+               for (i = 0; i < nelems; i++, sg++)
                        __dma_sync(sg_page(sg), sg->offset, sg->length,
                                   direction);
-       }
 }
 
 static void mips_dma_sync_sg_for_device(struct device *dev,
@@ -320,12 +319,10 @@ static void mips_dma_sync_sg_for_device(struct device *dev,
 {
        int i;
 
-       /* Make sure that gcc doesn't leave the empty loop body.  */
-       for (i = 0; i < nelems; i++, sg++) {
-               if (!plat_device_is_coherent(dev))
+       if (!plat_device_is_coherent(dev))
+               for (i = 0; i < nelems; i++, sg++)
                        __dma_sync(sg_page(sg), sg->offset, sg->length,
                                   direction);
-       }
 }
 
 int mips_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
index 218c2109a55d7fd6f4be10e1e860f00e50c2bc7f..cbd81d17793a71b617ed28b92a2510d89d08114a 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <asm/bugs.h>
 #include <asm/cacheops.h>
+#include <asm/cpu-type.h>
 #include <asm/inst.h>
 #include <asm/io.h>
 #include <asm/page.h>
index 5d01392e3518d1166b1cf82c6bee69475a30021e..08d05aee8788beecdf0a6e3cc8d21ee3901e17da 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 
+#include <asm/cpu-type.h>
 #include <asm/mipsregs.h>
 #include <asm/bcache.h>
 #include <asm/cacheops.h>
@@ -71,7 +72,7 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
        unsigned int tmp;
 
        /* Check the bypass bit (L2B) */
-       switch (c->cputype) {
+       switch (current_cpu_type()) {
        case CPU_34K:
        case CPU_74K:
        case CPU_1004K:
index 00b26a67a06d8c0693f15999aa08db864dbe2a93..bb3a5f643e974a27a7d81246d4d7bb6b5f13a390 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 
 #include <asm/cpu.h>
+#include <asm/cpu-type.h>
 #include <asm/bootinfo.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
index 821b45175dc1a961c3f86a799228ab5a3eb512cf..9bb3a9363b0618df3e19a43fafc68eb91dff18ba 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/cache.h>
 
 #include <asm/cacheflush.h>
+#include <asm/cpu-type.h>
 #include <asm/pgtable.h>
 #include <asm/war.h>
 #include <asm/uasm.h>
index 53aad4a3537569d3a33b1953c1d42b76db6e40e3..a18af5fce67eb704d223742f6f15f7062604ff7b 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/timex.h>
 #include <linux/mc146818rtc.h>
 
+#include <asm/cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
 #include <asm/hardirq.h>
@@ -76,7 +77,7 @@ static void __init estimate_frequencies(void)
 #endif
 
 #if defined (CONFIG_KVM_GUEST) && defined (CONFIG_KVM_HOST_FREQ)
-       unsigned int prid = read_c0_prid() & 0xffff00;
+       unsigned int prid = read_c0_prid() & (PRID_COMP_MASK | PRID_IMP_MASK);
 
        /*
         * XXXKYMA: hardwire the CPU frequency to Host Freq/4
@@ -169,7 +170,7 @@ unsigned int get_c0_compare_int(void)
 
 void __init plat_time_init(void)
 {
-       unsigned int prid = read_c0_prid() & 0xffff00;
+       unsigned int prid = read_c0_prid() & (PRID_COMP_MASK | PRID_IMP_MASK);
        unsigned int freq;
 
        estimate_frequencies();
index a43ea3cc0a3bf61bdbe458f3e38b639ea896b319..552d26c343869fe6c02778dec476215626a7b356 100644 (file)
@@ -7,6 +7,7 @@
  */
 #include <linux/init.h>
 
+#include <asm/cpu.h>
 #include <asm/setup.h>
 #include <asm/time.h>
 #include <asm/irq.h>
@@ -34,7 +35,7 @@ static void __iomem *status_reg = (void __iomem *)0xbf000410;
  */
 static unsigned int __init estimate_cpu_frequency(void)
 {
-       unsigned int prid = read_c0_prid() & 0xffff00;
+       unsigned int prid = read_c0_prid() & (PRID_COMP_MASK | PRID_IMP_MASK);
        unsigned int tick = 0;
        unsigned int freq;
        unsigned int orig;
index ed3bf0e3f3093d7004d984bfb59c4ed8cce7cab1..c7622c6e5f676cd8f20a6a926487029d8ba47ea1 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 
+#include <asm/cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/netlogic/xlr/fmn.h>
 #include <asm/netlogic/xlr/xlr.h>
@@ -187,7 +188,7 @@ void xlr_board_info_setup(void)
        int processor_id, num_core;
 
        num_core = hweight32(nlm_current_node()->coremask);
-       processor_id = read_c0_prid() & 0xff00;
+       processor_id = read_c0_prid() & PRID_IMP_MASK;
 
        setup_cpu_fmninfo(cpu, num_core);
        switch (processor_id) {
index 5e5424753b5624b9c66511db86d7c98fed11d2f0..4d1736fc19557b793fd707f2543500a043bf6488 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/oprofile.h>
 #include <linux/smp.h>
 #include <asm/cpu-info.h>
+#include <asm/cpu-type.h>
 
 #include "op_impl.h"
 
index 44dd5aa2e36f2d44fdc78ef9baca79234c80d510..5ec2a7bae02c80b1d9894e1c77e5cad4f99336a1 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/mm.h>
 #include <linux/console.h>
 #include <linux/tty.h>
+#include <linux/vt.h>
 
 #include <asm/sibyte/bcm1480_regs.h>
 #include <asm/sibyte/bcm1480_scd.h>
index 05ed92c92b696f20d6c1356086ef3f79d94026f6..8e2e04f7787068bdd2d3421d14b33ef3cc283867 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/string.h>
 
 #include <asm/bootinfo.h>
+#include <asm/cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/io.h>
 #include <asm/sibyte/sb1250.h>
@@ -119,7 +120,7 @@ void __init bcm1480_setup(void)
        uint64_t sys_rev;
        int plldiv;
 
-       sb1_pass = read_c0_prid() & 0xff;
+       sb1_pass = read_c0_prid() & PRID_REV_MASK;
        sys_rev = __raw_readq(IOADDR(A_SCD_SYSTEM_REVISION));
        soc_type = SYS_SOC_TYPE(sys_rev);
        part_type = G_SYS_PART(sys_rev);
index a14bd4cb0bc0cd70fd2468b0cea55ad5ba9da091..3c02b2a77ae996b0d84ebe085fe697d6879cb144 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/string.h>
 
 #include <asm/bootinfo.h>
+#include <asm/cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/io.h>
 #include <asm/sibyte/sb1250.h>
@@ -182,7 +183,7 @@ void __init sb1250_setup(void)
        int plldiv;
        int bad_config = 0;
 
-       sb1_pass = read_c0_prid() & 0xff;
+       sb1_pass = read_c0_prid() & PRID_REV_MASK;
        sys_rev = __raw_readq(IOADDR(A_SCD_SYSTEM_REVISION));
        soc_type = SYS_SOC_TYPE(sys_rev);
        soc_pass = G_SYS_REVISION(sys_rev);
index 5b09b3544edd156583603d37e3575669f6211fd2..efad85c8c823b9377c88322d5def836eb494eb59 100644 (file)
@@ -25,6 +25,7 @@
 #endif
 
 #include <asm/bootinfo.h>
+#include <asm/cpu.h>
 #include <asm/io.h>
 #include <asm/reboot.h>
 #include <asm/sni.h>
@@ -173,7 +174,7 @@ void __init plat_mem_setup(void)
                system_type = "RM300-Cxx";
                break;
        case SNI_BRD_PCI_DESKTOP:
-               switch (read_c0_prid() & 0xff00) {
+               switch (read_c0_prid() & PRID_IMP_MASK) {
                case PRID_IMP_R4600:
                case PRID_IMP_R4700:
                        system_type = "RM200-C20";
index eb59bfe23e8510c7c812d43496860bcee37974b7..93c9980e1b6b61a93c81dc93a4c0902ee59a451c 100644 (file)
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-
-#include <linux/of.h>  /* linux/of.h gets to determine #include ordering */
-
 #ifndef _ASM_OPENRISC_PROM_H
 #define _ASM_OPENRISC_PROM_H
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
 
-#include <linux/types.h>
-#include <asm/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/atomic.h>
-#include <linux/of_irq.h>
-#include <linux/of_fdt.h>
-#include <linux/of_address.h>
-#include <linux/proc_fs.h>
-#include <linux/platform_device.h>
 #define HAVE_ARCH_DEVTREE_FIXUPS
 
-/* Other Prototypes */
-extern int early_uartlite_console(void);
-
-/* Parse the ibm,dma-window property of an OF node into the busno, phys and
- * size parameters.
- */
-void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
-               unsigned long *busno, unsigned long *phys, unsigned long *size);
-
-extern void kdump_move_device_tree(void);
-
-/* Get the MAC address */
-extern const void *of_get_mac_address(struct device_node *np);
-
-/**
- * of_irq_map_pci - Resolve the interrupt for a PCI device
- * @pdev:      the device whose interrupt is to be resolved
- * @out_irq:   structure of_irq filled by this function
- *
- * This function resolves the PCI interrupt for a given PCI device. If a
- * device-node exists for a given pci_dev, it will use normal OF tree
- * walking. If not, it will implement standard swizzling and walk up the
- * PCI tree until an device-node is found, at which point it will finish
- * resolving using the OF tree walking.
- */
-struct pci_dev;
-extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
-
-#endif /* __ASSEMBLY__ */
-#endif /* __KERNEL__ */
 #endif /* _ASM_OPENRISC_PROM_H */
index d10d27a720c0d1f323c2248f01cc93193e73ca1e..00c0ed333a3d53421a161369cf1fa621c8a02d7f 100644 (file)
@@ -182,6 +182,9 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
 
        if (user_mode(regs))
                flags |= FAULT_FLAG_USER;
+
+       acc_type = parisc_acctyp(code, regs->iir);
+
        if (acc_type & VM_WRITE)
                flags |= FAULT_FLAG_WRITE;
 retry:
@@ -196,8 +199,6 @@ retry:
 
 good_area:
 
-       acc_type = parisc_acctyp(code,regs->iir);
-
        if ((vma->vm_flags & acc_type) != acc_type)
                goto bad_area;
 
index 6a15c968d21453230ab469b5921fea28b790dcc5..15ca2255f43853945789c1fdc58f4a5bc5a82dbf 100644 (file)
@@ -74,7 +74,7 @@ src-wlib-$(CONFIG_8xx) += mpc8xx.c planetcore.c
 src-wlib-$(CONFIG_PPC_82xx) += pq2.c fsl-soc.c planetcore.c
 src-wlib-$(CONFIG_EMBEDDED6xx) += mv64x60.c mv64x60_i2c.c ugecon.c
 
-src-plat-y := of.c
+src-plat-y := of.c epapr.c
 src-plat-$(CONFIG_40x) += fixed-head.S ep405.c cuboot-hotfoot.c \
                                treeboot-walnut.c cuboot-acadia.c \
                                cuboot-kilauea.c simpleboot.c \
@@ -97,7 +97,7 @@ src-plat-$(CONFIG_EMBEDDED6xx) += cuboot-pq2.c cuboot-mpc7448hpc2.c \
                                        prpmc2800.c
 src-plat-$(CONFIG_AMIGAONE) += cuboot-amigaone.c
 src-plat-$(CONFIG_PPC_PS3) += ps3-head.S ps3-hvcall.S ps3.c
-src-plat-$(CONFIG_EPAPR_BOOT) += epapr.c
+src-plat-$(CONFIG_EPAPR_BOOT) += epapr.c epapr-wrapper.c
 
 src-wlib := $(sort $(src-wlib-y))
 src-plat := $(sort $(src-plat-y))
diff --git a/arch/powerpc/boot/epapr-wrapper.c b/arch/powerpc/boot/epapr-wrapper.c
new file mode 100644 (file)
index 0000000..c101910
--- /dev/null
@@ -0,0 +1,9 @@
+extern void epapr_platform_init(unsigned long r3, unsigned long r4,
+                               unsigned long r5, unsigned long r6,
+                               unsigned long r7);
+
+void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+                  unsigned long r6, unsigned long r7)
+{
+       epapr_platform_init(r3, r4, r5, r6, r7);
+}
index 06c1961bd124a06966da1c5c6a85a6d4452e951a..02e91aa2194a57a66766852444835607143fa29a 100644 (file)
@@ -48,8 +48,8 @@ static void platform_fixups(void)
                       fdt_addr, fdt_totalsize((void *)fdt_addr), ima_size);
 }
 
-void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-                  unsigned long r6, unsigned long r7)
+void epapr_platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+                        unsigned long r6, unsigned long r7)
 {
        epapr_magic = r6;
        ima_size = r7;
index 61d9899aa0d09d371c99ec70b7959693f8bfab36..62e2f43ec1df1144d3a790e1f3cf3e3263fdca47 100644 (file)
@@ -26,6 +26,9 @@
 
 static unsigned long claim_base;
 
+void epapr_platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+                        unsigned long r6, unsigned long r7);
+
 static void *of_try_claim(unsigned long size)
 {
        unsigned long addr = 0;
@@ -61,7 +64,7 @@ static void of_image_hdr(const void *hdr)
        }
 }
 
-void platform_init(unsigned long a1, unsigned long a2, void *promptr)
+static void of_platform_init(unsigned long a1, unsigned long a2, void *promptr)
 {
        platform_ops.image_hdr = of_image_hdr;
        platform_ops.malloc = of_try_claim;
@@ -81,3 +84,14 @@ void platform_init(unsigned long a1, unsigned long a2, void *promptr)
                loader_info.initrd_size = a2;
        }
 }
+
+void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+                  unsigned long r6, unsigned long r7)
+{
+       /* Detect OF vs. ePAPR boot */
+       if (r5)
+               of_platform_init(r3, r4, (void *)r5);
+       else
+               epapr_platform_init(r3, r4, r5, r6, r7);
+}
+
index 6761c746048df389812888b8430aca4f442e191c..cd7af841ba051f8725e8ab33dffae1a23201fc60 100755 (executable)
@@ -148,18 +148,18 @@ make_space=y
 
 case "$platform" in
 pseries)
-    platformo=$object/of.o
+    platformo="$object/of.o $object/epapr.o"
     link_address='0x4000000'
     ;;
 maple)
-    platformo=$object/of.o
+    platformo="$object/of.o $object/epapr.o"
     link_address='0x400000'
     ;;
 pmac|chrp)
-    platformo=$object/of.o
+    platformo="$object/of.o $object/epapr.o"
     ;;
 coff)
-    platformo="$object/crt0.o $object/of.o"
+    platformo="$object/crt0.o $object/of.o $object/epapr.o"
     lds=$object/zImage.coff.lds
     link_address='0x500000'
     pie=
@@ -253,6 +253,7 @@ treeboot-iss4xx-mpic)
     platformo="$object/treeboot-iss4xx.o"
     ;;
 epapr)
+    platformo="$object/epapr.o $object/epapr-wrapper.o"
     link_address='0x20000000'
     pie=-pie
     ;;
index 0e40843a1c6ed58273c1a0e2eb22841e9007e977..41f13cec8a8fcd01bbd2e02f3cfc50083b3addba 100644 (file)
@@ -69,9 +69,9 @@ extern struct thread_info *softirq_ctx[NR_CPUS];
 
 extern void irq_ctx_init(void);
 extern void call_do_softirq(struct thread_info *tp);
-extern int call_handle_irq(int irq, void *p1,
-                          struct thread_info *tp, void *func);
+extern void call_do_irq(struct pt_regs *regs, struct thread_info *tp);
 extern void do_IRQ(struct pt_regs *regs);
+extern void __do_irq(struct pt_regs *regs);
 
 int irq_choose_cpu(const struct cpumask *mask);
 
index e378cccfca55bb20db094f12a2009ad3ba7bf1a4..ce4de5aed7b5c302b292bd38c69f21bd2f059038 100644 (file)
@@ -149,8 +149,6 @@ typedef struct {
 
 struct thread_struct {
        unsigned long   ksp;            /* Kernel stack pointer */
-       unsigned long   ksp_limit;      /* if ksp <= ksp_limit stack overflow */
-
 #ifdef CONFIG_PPC64
        unsigned long   ksp_vsid;
 #endif
@@ -162,6 +160,7 @@ struct thread_struct {
 #endif
 #ifdef CONFIG_PPC32
        void            *pgdir;         /* root of page-table tree */
+       unsigned long   ksp_limit;      /* if ksp <= ksp_limit stack overflow */
 #endif
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
        /*
@@ -321,7 +320,6 @@ struct thread_struct {
 #else
 #define INIT_THREAD  { \
        .ksp = INIT_SP, \
-       .ksp_limit = INIT_SP_LIMIT, \
        .regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \
        .fs = KERNEL_DS, \
        .fpr = {{0}}, \
index d8958be5f31a18b7c0bae16509749067aae75265..502c7a4e73f70dc1008754b7f55e5ae164f25a76 100644 (file)
@@ -80,10 +80,11 @@ int main(void)
        DEFINE(TASKTHREADPPR, offsetof(struct task_struct, thread.ppr));
 #else
        DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
+       DEFINE(THREAD_INFO_GAP, _ALIGN_UP(sizeof(struct thread_info), 16));
+       DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit));
 #endif /* CONFIG_PPC64 */
 
        DEFINE(KSP, offsetof(struct thread_struct, ksp));
-       DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit));
        DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
 #ifdef CONFIG_BOOKE
        DEFINE(THREAD_NORMSAVES, offsetof(struct thread_struct, normsave[0]));
index 0adab06ce5c0aaa3e73818951bb4764b047b9a61..572bb5b95f35d815f6f24fe7b59a67bf420fbe2b 100644 (file)
@@ -661,7 +661,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
        /* number of bytes needed for the bitmap */
        sz = BITS_TO_LONGS(tbl->it_size) * sizeof(unsigned long);
 
-       page = alloc_pages_node(nid, GFP_ATOMIC, get_order(sz));
+       page = alloc_pages_node(nid, GFP_KERNEL, get_order(sz));
        if (!page)
                panic("iommu_init_table: Can't allocate %ld bytes\n", sz);
        tbl->it_map = page_address(page);
index c69440cef7af43413987f3cd4b2c936cd0e8f788..57d286a78f86f6ff1231c695b9a10a591af30710 100644 (file)
@@ -441,50 +441,6 @@ void migrate_irqs(void)
 }
 #endif
 
-static inline void handle_one_irq(unsigned int irq)
-{
-       struct thread_info *curtp, *irqtp;
-       unsigned long saved_sp_limit;
-       struct irq_desc *desc;
-
-       desc = irq_to_desc(irq);
-       if (!desc)
-               return;
-
-       /* Switch to the irq stack to handle this */
-       curtp = current_thread_info();
-       irqtp = hardirq_ctx[smp_processor_id()];
-
-       if (curtp == irqtp) {
-               /* We're already on the irq stack, just handle it */
-               desc->handle_irq(irq, desc);
-               return;
-       }
-
-       saved_sp_limit = current->thread.ksp_limit;
-
-       irqtp->task = curtp->task;
-       irqtp->flags = 0;
-
-       /* Copy the softirq bits in preempt_count so that the
-        * softirq checks work in the hardirq context. */
-       irqtp->preempt_count = (irqtp->preempt_count & ~SOFTIRQ_MASK) |
-                              (curtp->preempt_count & SOFTIRQ_MASK);
-
-       current->thread.ksp_limit = (unsigned long)irqtp +
-               _ALIGN_UP(sizeof(struct thread_info), 16);
-
-       call_handle_irq(irq, desc, irqtp, desc->handle_irq);
-       current->thread.ksp_limit = saved_sp_limit;
-       irqtp->task = NULL;
-
-       /* Set any flag that may have been set on the
-        * alternate stack
-        */
-       if (irqtp->flags)
-               set_bits(irqtp->flags, &curtp->flags);
-}
-
 static inline void check_stack_overflow(void)
 {
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
@@ -501,9 +457,9 @@ static inline void check_stack_overflow(void)
 #endif
 }
 
-void do_IRQ(struct pt_regs *regs)
+void __do_irq(struct pt_regs *regs)
 {
-       struct pt_regs *old_regs = set_irq_regs(regs);
+       struct irq_desc *desc;
        unsigned int irq;
 
        irq_enter();
@@ -519,18 +475,56 @@ void do_IRQ(struct pt_regs *regs)
         */
        irq = ppc_md.get_irq();
 
-       /* We can hard enable interrupts now */
+       /* We can hard enable interrupts now to allow perf interrupts */
        may_hard_irq_enable();
 
        /* And finally process it */
-       if (irq != NO_IRQ)
-               handle_one_irq(irq);
-       else
+       if (unlikely(irq == NO_IRQ))
                __get_cpu_var(irq_stat).spurious_irqs++;
+       else {
+               desc = irq_to_desc(irq);
+               if (likely(desc))
+                       desc->handle_irq(irq, desc);
+       }
 
        trace_irq_exit(regs);
 
        irq_exit();
+}
+
+void do_IRQ(struct pt_regs *regs)
+{
+       struct pt_regs *old_regs = set_irq_regs(regs);
+       struct thread_info *curtp, *irqtp;
+
+       /* Switch to the irq stack to handle this */
+       curtp = current_thread_info();
+       irqtp = hardirq_ctx[raw_smp_processor_id()];
+
+       /* Already there ? */
+       if (unlikely(curtp == irqtp)) {
+               __do_irq(regs);
+               set_irq_regs(old_regs);
+               return;
+       }
+
+       /* Prepare the thread_info in the irq stack */
+       irqtp->task = curtp->task;
+       irqtp->flags = 0;
+
+       /* Copy the preempt_count so that the [soft]irq checks work. */
+       irqtp->preempt_count = curtp->preempt_count;
+
+       /* Switch stack and call */
+       call_do_irq(regs, irqtp);
+
+       /* Restore stack limit */
+       irqtp->task = NULL;
+
+       /* Copy back updates to the thread_info */
+       if (irqtp->flags)
+               set_bits(irqtp->flags, &curtp->flags);
+
        set_irq_regs(old_regs);
 }
 
@@ -592,28 +586,22 @@ void irq_ctx_init(void)
                memset((void *)softirq_ctx[i], 0, THREAD_SIZE);
                tp = softirq_ctx[i];
                tp->cpu = i;
-               tp->preempt_count = 0;
 
                memset((void *)hardirq_ctx[i], 0, THREAD_SIZE);
                tp = hardirq_ctx[i];
                tp->cpu = i;
-               tp->preempt_count = HARDIRQ_OFFSET;
        }
 }
 
 static inline void do_softirq_onstack(void)
 {
        struct thread_info *curtp, *irqtp;
-       unsigned long saved_sp_limit = current->thread.ksp_limit;
 
        curtp = current_thread_info();
        irqtp = softirq_ctx[smp_processor_id()];
        irqtp->task = curtp->task;
        irqtp->flags = 0;
-       current->thread.ksp_limit = (unsigned long)irqtp +
-                                   _ALIGN_UP(sizeof(struct thread_info), 16);
        call_do_softirq(irqtp);
-       current->thread.ksp_limit = saved_sp_limit;
        irqtp->task = NULL;
 
        /* Set any flag that may have been set on the
index 777d999f563bb377bff3217358aacdc7667f1fd4..2b0ad984536333d7a15a3b39e6c9234c11b4b669 100644 (file)
 
        .text
 
+/*
+ * We store the saved ksp_limit in the unused part
+ * of the STACK_FRAME_OVERHEAD
+ */
 _GLOBAL(call_do_softirq)
        mflr    r0
        stw     r0,4(r1)
+       lwz     r10,THREAD+KSP_LIMIT(r2)
+       addi    r11,r3,THREAD_INFO_GAP
        stwu    r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
        mr      r1,r3
+       stw     r10,8(r1)
+       stw     r11,THREAD+KSP_LIMIT(r2)
        bl      __do_softirq
+       lwz     r10,8(r1)
        lwz     r1,0(r1)
        lwz     r0,4(r1)
+       stw     r10,THREAD+KSP_LIMIT(r2)
        mtlr    r0
        blr
 
-_GLOBAL(call_handle_irq)
+_GLOBAL(call_do_irq)
        mflr    r0
        stw     r0,4(r1)
-       mtctr   r6
-       stwu    r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r5)
-       mr      r1,r5
-       bctrl
+       lwz     r10,THREAD+KSP_LIMIT(r2)
+       addi    r11,r3,THREAD_INFO_GAP
+       stwu    r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r4)
+       mr      r1,r4
+       stw     r10,8(r1)
+       stw     r11,THREAD+KSP_LIMIT(r2)
+       bl      __do_irq
+       lwz     r10,8(r1)
        lwz     r1,0(r1)
        lwz     r0,4(r1)
+       stw     r10,THREAD+KSP_LIMIT(r2)
        mtlr    r0
        blr
 
index 971d7e78aff20e1ca801dd923dfc77337e834ad5..e59caf874d05ed60e500579b06bfcdf38bd85125 100644 (file)
@@ -40,14 +40,12 @@ _GLOBAL(call_do_softirq)
        mtlr    r0
        blr
 
-_GLOBAL(call_handle_irq)
-       ld      r8,0(r6)
+_GLOBAL(call_do_irq)
        mflr    r0
        std     r0,16(r1)
-       mtctr   r8
-       stdu    r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r5)
-       mr      r1,r5
-       bctrl
+       stdu    r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r4)
+       mr      r1,r4
+       bl      .__do_irq
        ld      r1,0(r1)
        ld      r0,16(r1)
        mtlr    r0
index 6f428da53e2085b877334270286069e2ba54da37..96d2fdf3aa9ebe3bba547fd567c5a232be20ec9a 100644 (file)
@@ -1000,9 +1000,10 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        kregs = (struct pt_regs *) sp;
        sp -= STACK_FRAME_OVERHEAD;
        p->thread.ksp = sp;
+#ifdef CONFIG_PPC32
        p->thread.ksp_limit = (unsigned long)task_stack_page(p) +
                                _ALIGN_UP(sizeof(struct thread_info), 16);
-
+#endif
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
        p->thread.ptrace_bps[0] = NULL;
 #endif
index 12e656ffe60ea86a00a531578efd55ef98e3faef..5fe2842e8bab7cc4013c987c74791c00005c51ee 100644 (file)
@@ -196,6 +196,8 @@ static int __initdata mem_reserve_cnt;
 
 static cell_t __initdata regbuf[1024];
 
+static bool rtas_has_query_cpu_stopped;
+
 
 /*
  * Error results ... some OF calls will return "-1" on error, some
@@ -1574,6 +1576,11 @@ static void __init prom_instantiate_rtas(void)
        prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
                     &val, sizeof(val));
 
+       /* Check if it supports "query-cpu-stopped-state" */
+       if (prom_getprop(rtas_node, "query-cpu-stopped-state",
+                        &val, sizeof(val)) != PROM_ERROR)
+               rtas_has_query_cpu_stopped = true;
+
 #if defined(CONFIG_PPC_POWERNV) && defined(__BIG_ENDIAN__)
        /* PowerVN takeover hack */
        prom_rtas_data = base;
@@ -1815,6 +1822,18 @@ static void __init prom_hold_cpus(void)
                = (void *) LOW_ADDR(__secondary_hold_acknowledge);
        unsigned long secondary_hold = LOW_ADDR(__secondary_hold);
 
+       /*
+        * On pseries, if RTAS supports "query-cpu-stopped-state",
+        * we skip this stage, the CPUs will be started by the
+        * kernel using RTAS.
+        */
+       if ((of_platform == PLATFORM_PSERIES ||
+            of_platform == PLATFORM_PSERIES_LPAR) &&
+           rtas_has_query_cpu_stopped) {
+               prom_printf("prom_hold_cpus: skipped\n");
+               return;
+       }
+
        prom_debug("prom_hold_cpus: start...\n");
        prom_debug("    1) spinloop       = 0x%x\n", (unsigned long)spinloop);
        prom_debug("    1) *spinloop      = 0x%x\n", *spinloop);
@@ -3011,6 +3030,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
         * On non-powermacs, put all CPUs in spin-loops.
         *
         * PowerMacs use a different mechanism to spin CPUs
+        *
+        * (This must be done after instanciating RTAS)
         */
        if (of_platform != PLATFORM_POWERMAC &&
            of_platform != PLATFORM_OPAL)
index 27a90b99ef6744d20fa6664bb1c6244626a5cd0d..b4e667663d9bfc2e9954435790b0ebc5b6fc94ca 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/machdep.h>
 #include <asm/smp.h>
 #include <asm/pmc.h>
+#include <asm/firmware.h>
 
 #include "cacheinfo.h"
 
@@ -179,15 +180,25 @@ SYSFS_PMCSETUP(spurr, SPRN_SPURR);
 SYSFS_PMCSETUP(dscr, SPRN_DSCR);
 SYSFS_PMCSETUP(pir, SPRN_PIR);
 
+/*
+  Lets only enable read for phyp resources and
+  enable write when needed with a separate function.
+  Lets be conservative and default to pseries.
+*/
 static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra);
 static DEVICE_ATTR(spurr, 0400, show_spurr, NULL);
 static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr);
-static DEVICE_ATTR(purr, 0600, show_purr, store_purr);
+static DEVICE_ATTR(purr, 0400, show_purr, store_purr);
 static DEVICE_ATTR(pir, 0400, show_pir, NULL);
 
 unsigned long dscr_default = 0;
 EXPORT_SYMBOL(dscr_default);
 
+static void add_write_permission_dev_attr(struct device_attribute *attr)
+{
+       attr->attr.mode |= 0200;
+}
+
 static ssize_t show_dscr_default(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
@@ -394,8 +405,11 @@ static void register_cpu_online(unsigned int cpu)
        if (cpu_has_feature(CPU_FTR_MMCRA))
                device_create_file(s, &dev_attr_mmcra);
 
-       if (cpu_has_feature(CPU_FTR_PURR))
+       if (cpu_has_feature(CPU_FTR_PURR)) {
+               if (!firmware_has_feature(FW_FEATURE_LPAR))
+                       add_write_permission_dev_attr(&dev_attr_purr);
                device_create_file(s, &dev_attr_purr);
+       }
 
        if (cpu_has_feature(CPU_FTR_SPURR))
                device_create_file(s, &dev_attr_spurr);
index 7b60b98514691ee554d1140e408c9802f83d21a4..cd809eaa8b5c4bec7d00497e0edaa614501f13e0 100644 (file)
@@ -79,6 +79,11 @@ _GLOBAL(tm_abort)
        TABORT(R3)
        blr
 
+       .section        ".toc","aw"
+DSCR_DEFAULT:
+       .tc dscr_default[TC],dscr_default
+
+       .section        ".text"
 
 /* void tm_reclaim(struct thread_struct *thread,
  *                 unsigned long orig_msr,
@@ -123,6 +128,7 @@ _GLOBAL(tm_reclaim)
        mr      r15, r14
        ori     r15, r15, MSR_FP
        li      r16, MSR_RI
+       ori     r16, r16, MSR_EE /* IRQs hard off */
        andc    r15, r15, r16
        oris    r15, r15, MSR_VEC@h
 #ifdef CONFIG_VSX
@@ -187,11 +193,18 @@ dont_backup_fp:
        std     r1, PACATMSCRATCH(r13)
        ld      r1, PACAR1(r13)
 
+       /* Store the PPR in r11 and reset to decent value */
+       std     r11, GPR11(r1)                  /* Temporary stash */
+       mfspr   r11, SPRN_PPR
+       HMT_MEDIUM
+
        /* Now get some more GPRS free */
        std     r7, GPR7(r1)                    /* Temporary stash */
        std     r12, GPR12(r1)                  /* ''   ''    ''   */
        ld      r12, STACK_PARAM(0)(r1)         /* Param 0, thread_struct * */
 
+       std     r11, THREAD_TM_PPR(r12)         /* Store PPR and free r11 */
+
        addi    r7, r12, PT_CKPT_REGS           /* Thread's ckpt_regs */
 
        /* Make r7 look like an exception frame so that we
@@ -203,15 +216,19 @@ dont_backup_fp:
        SAVE_GPR(0, r7)                         /* user r0 */
        SAVE_GPR(2, r7)                 /* user r2 */
        SAVE_4GPRS(3, r7)                       /* user r3-r6 */
-       SAVE_4GPRS(8, r7)                       /* user r8-r11 */
+       SAVE_GPR(8, r7)                         /* user r8 */
+       SAVE_GPR(9, r7)                         /* user r9 */
+       SAVE_GPR(10, r7)                        /* user r10 */
        ld      r3, PACATMSCRATCH(r13)          /* user r1 */
        ld      r4, GPR7(r1)                    /* user r7 */
-       ld      r5, GPR12(r1)                   /* user r12 */
-       GET_SCRATCH0(6)                         /* user r13 */
+       ld      r5, GPR11(r1)                   /* user r11 */
+       ld      r6, GPR12(r1)                   /* user r12 */
+       GET_SCRATCH0(8)                         /* user r13 */
        std     r3, GPR1(r7)
        std     r4, GPR7(r7)
-       std     r5, GPR12(r7)
-       std     r6, GPR13(r7)
+       std     r5, GPR11(r7)
+       std     r6, GPR12(r7)
+       std     r8, GPR13(r7)
 
        SAVE_NVGPRS(r7)                         /* user r14-r31 */
 
@@ -234,14 +251,12 @@ dont_backup_fp:
        std     r6, _XER(r7)
 
 
-       /* ******************** TAR, PPR, DSCR ********** */
+       /* ******************** TAR, DSCR ********** */
        mfspr   r3, SPRN_TAR
-       mfspr   r4, SPRN_PPR
-       mfspr   r5, SPRN_DSCR
+       mfspr   r4, SPRN_DSCR
 
        std     r3, THREAD_TM_TAR(r12)
-       std     r4, THREAD_TM_PPR(r12)
-       std     r5, THREAD_TM_DSCR(r12)
+       std     r4, THREAD_TM_DSCR(r12)
 
        /* MSR and flags:  We don't change CRs, and we don't need to alter
         * MSR.
@@ -258,7 +273,7 @@ dont_backup_fp:
        std     r3, THREAD_TM_TFHAR(r12)
        std     r4, THREAD_TM_TFIAR(r12)
 
-       /* AMR and PPR are checkpointed too, but are unsupported by Linux. */
+       /* AMR is checkpointed too, but is unsupported by Linux. */
 
        /* Restore original MSR/IRQ state & clear TM mode */
        ld      r14, TM_FRAME_L0(r1)            /* Orig MSR */
@@ -274,6 +289,12 @@ dont_backup_fp:
        mtcr    r4
        mtlr    r0
        ld      r2, 40(r1)
+
+       /* Load system default DSCR */
+       ld      r4, DSCR_DEFAULT@toc(r2)
+       ld      r0, 0(r4)
+       mtspr   SPRN_DSCR, r0
+
        blr
 
 
@@ -358,25 +379,24 @@ dont_restore_fp:
 
 restore_gprs:
 
-       /* ******************** TAR, PPR, DSCR ********** */
-       ld      r4, THREAD_TM_TAR(r3)
-       ld      r5, THREAD_TM_PPR(r3)
-       ld      r6, THREAD_TM_DSCR(r3)
+       /* ******************** CR,LR,CCR,MSR ********** */
+       ld      r4, _CTR(r7)
+       ld      r5, _LINK(r7)
+       ld      r6, _CCR(r7)
+       ld      r8, _XER(r7)
 
-       mtspr   SPRN_TAR,       r4
-       mtspr   SPRN_PPR,       r5
-       mtspr   SPRN_DSCR,      r6
+       mtctr   r4
+       mtlr    r5
+       mtcr    r6
+       mtxer   r8
 
-       /* ******************** CR,LR,CCR,MSR ********** */
-       ld      r3, _CTR(r7)
-       ld      r4, _LINK(r7)
-       ld      r5, _CCR(r7)
-       ld      r6, _XER(r7)
+       /* ******************** TAR ******************** */
+       ld      r4, THREAD_TM_TAR(r3)
+       mtspr   SPRN_TAR,       r4
 
-       mtctr   r3
-       mtlr    r4
-       mtcr    r5
-       mtxer   r6
+       /* Load up the PPR and DSCR in GPRs only at this stage */
+       ld      r5, THREAD_TM_DSCR(r3)
+       ld      r6, THREAD_TM_PPR(r3)
 
        /* Clear the MSR RI since we are about to change R1.  EE is already off
         */
@@ -384,19 +404,26 @@ restore_gprs:
        mtmsrd  r4, 1
 
        REST_4GPRS(0, r7)                       /* GPR0-3 */
-       REST_GPR(4, r7)                         /* GPR4-6 */
-       REST_GPR(5, r7)
-       REST_GPR(6, r7)
+       REST_GPR(4, r7)                         /* GPR4 */
        REST_4GPRS(8, r7)                       /* GPR8-11 */
        REST_2GPRS(12, r7)                      /* GPR12-13 */
 
        REST_NVGPRS(r7)                         /* GPR14-31 */
 
-       ld      r7, GPR7(r7)                    /* GPR7 */
+       /* Load up PPR and DSCR here so we don't run with user values for long
+        */
+       mtspr   SPRN_DSCR, r5
+       mtspr   SPRN_PPR, r6
+
+       REST_GPR(5, r7)                         /* GPR5-7 */
+       REST_GPR(6, r7)
+       ld      r7, GPR7(r7)
 
        /* Commit register state as checkpointed state: */
        TRECHKPT
 
+       HMT_MEDIUM
+
        /* Our transactional state has now changed.
         *
         * Now just get out of here.  Transactional (current) state will be
@@ -419,6 +446,12 @@ restore_gprs:
        mtcr    r4
        mtlr    r0
        ld      r2, 40(r1)
+
+       /* Load system default DSCR */
+       ld      r4, DSCR_DEFAULT@toc(r2)
+       ld      r0, 0(r4)
+       mtspr   SPRN_DSCR, r0
+
        blr
 
        /* ****************************************************************** */
index 78a350670de32b4ba7013ea8fefe2ab5c0d5d626..089de12b9ab0946e324c4521e11936ae685b15da 100644 (file)
@@ -1413,8 +1413,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
 
                /* needed to ensure proper operation of coherent allocations
                 * later, in case driver doesn't set it explicitly */
-               dma_set_mask(&viodev->dev, DMA_BIT_MASK(64));
-               dma_set_coherent_mask(&viodev->dev, DMA_BIT_MASK(64));
+               dma_set_mask_and_coherent(&viodev->dev, DMA_BIT_MASK(64));
        }
 
        /* register with generic device framework */
@@ -1530,11 +1529,15 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
        const char *cp;
 
        dn = dev->of_node;
-       if (!dn)
-               return -ENODEV;
+       if (!dn) {
+               strcat(buf, "\n");
+               return strlen(buf);
+       }
        cp = of_get_property(dn, "compatible", NULL);
-       if (!cp)
-               return -ENODEV;
+       if (!cp) {
+               strcat(buf, "\n");
+               return strlen(buf);
+       }
 
        return sprintf(buf, "vio:T%sS%s\n", vio_dev->type, cp);
 }
index 167f72555d604dc6c24194e3bb9c1e0b3d021bc4..57a0720650576a9f72e98cece18a71e25045ec3a 100644 (file)
@@ -226,19 +226,35 @@ _GLOBAL(csum_partial)
        blr
 
 
-       .macro source
+       .macro srcnr
 100:
        .section __ex_table,"a"
        .align 3
-       .llong 100b,.Lsrc_error
+       .llong 100b,.Lsrc_error_nr
        .previous
        .endm
 
-       .macro dest
+       .macro source
+150:
+       .section __ex_table,"a"
+       .align 3
+       .llong 150b,.Lsrc_error
+       .previous
+       .endm
+
+       .macro dstnr
 200:
        .section __ex_table,"a"
        .align 3
-       .llong 200b,.Ldest_error
+       .llong 200b,.Ldest_error_nr
+       .previous
+       .endm
+
+       .macro dest
+250:
+       .section __ex_table,"a"
+       .align 3
+       .llong 250b,.Ldest_error
        .previous
        .endm
 
@@ -269,16 +285,16 @@ _GLOBAL(csum_partial_copy_generic)
        rldicl. r6,r3,64-1,64-2         /* r6 = (r3 & 0x3) >> 1 */
        beq     .Lcopy_aligned
 
-       li      r7,4
-       sub     r6,r7,r6
+       li      r9,4
+       sub     r6,r9,r6
        mtctr   r6
 
 1:
-source;        lhz     r6,0(r3)                /* align to doubleword */
+srcnr; lhz     r6,0(r3)                /* align to doubleword */
        subi    r5,r5,2
        addi    r3,r3,2
        adde    r0,r0,r6
-dest;  sth     r6,0(r4)
+dstnr; sth     r6,0(r4)
        addi    r4,r4,2
        bdnz    1b
 
@@ -392,10 +408,10 @@ dest;     std     r16,56(r4)
 
        mtctr   r6
 3:
-source;        ld      r6,0(r3)
+srcnr; ld      r6,0(r3)
        addi    r3,r3,8
        adde    r0,r0,r6
-dest;  std     r6,0(r4)
+dstnr; std     r6,0(r4)
        addi    r4,r4,8
        bdnz    3b
 
@@ -405,10 +421,10 @@ dest;     std     r6,0(r4)
        srdi.   r6,r5,2
        beq     .Lcopy_tail_halfword
 
-source;        lwz     r6,0(r3)
+srcnr; lwz     r6,0(r3)
        addi    r3,r3,4
        adde    r0,r0,r6
-dest;  stw     r6,0(r4)
+dstnr; stw     r6,0(r4)
        addi    r4,r4,4
        subi    r5,r5,4
 
@@ -416,10 +432,10 @@ dest;     stw     r6,0(r4)
        srdi.   r6,r5,1
        beq     .Lcopy_tail_byte
 
-source;        lhz     r6,0(r3)
+srcnr; lhz     r6,0(r3)
        addi    r3,r3,2
        adde    r0,r0,r6
-dest;  sth     r6,0(r4)
+dstnr; sth     r6,0(r4)
        addi    r4,r4,2
        subi    r5,r5,2
 
@@ -427,10 +443,10 @@ dest;     sth     r6,0(r4)
        andi.   r6,r5,1
        beq     .Lcopy_finish
 
-source;        lbz     r6,0(r3)
+srcnr; lbz     r6,0(r3)
        sldi    r9,r6,8                 /* Pad the byte out to 16 bits */
        adde    r0,r0,r9
-dest;  stb     r6,0(r4)
+dstnr; stb     r6,0(r4)
 
 .Lcopy_finish:
        addze   r0,r0                   /* add in final carry */
@@ -440,6 +456,11 @@ dest;      stb     r6,0(r4)
        blr
 
 .Lsrc_error:
+       ld      r14,STK_REG(R14)(r1)
+       ld      r15,STK_REG(R15)(r1)
+       ld      r16,STK_REG(R16)(r1)
+       addi    r1,r1,STACKFRAMESIZE
+.Lsrc_error_nr:
        cmpdi   0,r7,0
        beqlr
        li      r6,-EFAULT
@@ -447,6 +468,11 @@ dest;      stb     r6,0(r4)
        blr
 
 .Ldest_error:
+       ld      r14,STK_REG(R14)(r1)
+       ld      r15,STK_REG(R15)(r1)
+       ld      r16,STK_REG(R16)(r1)
+       addi    r1,r1,STACKFRAMESIZE
+.Ldest_error_nr:
        cmpdi   0,r8,0
        beqlr
        li      r6,-EFAULT
index a7ee978fb860c9ffd237d9fbafb716b724e3afec..b1faa1593c9067e68995e1cdc54dbb8465dce587 100644 (file)
@@ -1505,6 +1505,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
                 */
                if ((ra == 1) && !(regs->msr & MSR_PR) \
                        && (val3 >= (regs->gpr[1] - STACK_INT_FRAME_SIZE))) {
+#ifdef CONFIG_PPC32
                        /*
                         * Check if we will touch kernel sack overflow
                         */
@@ -1513,7 +1514,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
                                err = -EINVAL;
                                break;
                        }
-
+#endif /* CONFIG_PPC32 */
                        /*
                         * Check if we already set since that means we'll
                         * lose the previous value.
index d0cd9e4c6837d2d17620b0f646151d9a54408f71..8ed035d2edb5a51540d580e4b6a6a5a106b3a5f9 100644 (file)
@@ -300,5 +300,9 @@ void vmemmap_free(unsigned long start, unsigned long end)
 {
 }
 
+void register_page_bootmem_memmap(unsigned long section_nr,
+                                 struct page *start_page, unsigned long size)
+{
+}
 #endif /* CONFIG_SPARSEMEM_VMEMMAP */
 
index 1cf9c5b67f241f40f46b127024c4a659e95af221..3fa93dc7fe750a9f53c875493b969f1962bea9af 100644 (file)
@@ -297,12 +297,21 @@ void __init paging_init(void)
 }
 #endif /* ! CONFIG_NEED_MULTIPLE_NODES */
 
+static void __init register_page_bootmem_info(void)
+{
+       int i;
+
+       for_each_online_node(i)
+               register_page_bootmem_info_node(NODE_DATA(i));
+}
+
 void __init mem_init(void)
 {
 #ifdef CONFIG_SWIOTLB
        swiotlb_init(0);
 #endif
 
+       register_page_bootmem_info();
        high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
        set_max_mapnr(max_pfn);
        free_all_bootmem();
index 2ee4a707f0df85c37dba15c6ab5f4e7f84e553fc..a3f7abd2f13f7a0793ce4e2bdb00855f9724d108 100644 (file)
 #define MMCR1_UNIT_SHIFT(pmc)          (60 - (4 * ((pmc) - 1)))
 #define MMCR1_COMBINE_SHIFT(pmc)       (35 - ((pmc) - 1))
 #define MMCR1_PMCSEL_SHIFT(pmc)                (24 - (((pmc) - 1)) * 8)
+#define MMCR1_FAB_SHIFT                        36
 #define MMCR1_DC_QUAL_SHIFT            47
 #define MMCR1_IC_QUAL_SHIFT            46
 
@@ -388,8 +389,8 @@ static int power8_compute_mmcr(u64 event[], int n_ev,
                 * the threshold bits are used for the match value.
                 */
                if (event_is_fab_match(event[i])) {
-                       mmcr1 |= (event[i] >> EVENT_THR_CTL_SHIFT) &
-                                 EVENT_THR_CTL_MASK;
+                       mmcr1 |= ((event[i] >> EVENT_THR_CTL_SHIFT) &
+                                 EVENT_THR_CTL_MASK) << MMCR1_FAB_SHIFT;
                } else {
                        val = (event[i] >> EVENT_THR_CTL_SHIFT) & EVENT_THR_CTL_MASK;
                        mmcra |= val << MMCRA_THR_CTL_SHIFT;
index 1c1771a402501d00328c450cfaeb5942f360d3f4..24f58cb0a543ece1cb92242b36ec8e18c145f5be 100644 (file)
@@ -233,18 +233,24 @@ static void __init smp_init_pseries(void)
 
        alloc_bootmem_cpumask_var(&of_spin_mask);
 
-       /* Mark threads which are still spinning in hold loops. */
-       if (cpu_has_feature(CPU_FTR_SMT)) {
-               for_each_present_cpu(i) { 
-                       if (cpu_thread_in_core(i) == 0)
-                               cpumask_set_cpu(i, of_spin_mask);
-               }
-       } else {
-               cpumask_copy(of_spin_mask, cpu_present_mask);
+       /*
+        * Mark threads which are still spinning in hold loops
+        *
+        * We know prom_init will not have started them if RTAS supports
+        * query-cpu-stopped-state.
+        */
+       if (rtas_token("query-cpu-stopped-state") == RTAS_UNKNOWN_SERVICE) {
+               if (cpu_has_feature(CPU_FTR_SMT)) {
+                       for_each_present_cpu(i) {
+                               if (cpu_thread_in_core(i) == 0)
+                                       cpumask_set_cpu(i, of_spin_mask);
+                       }
+               } else
+                       cpumask_copy(of_spin_mask, cpu_present_mask);
+
+               cpumask_clear_cpu(boot_cpuid, of_spin_mask);
        }
 
-       cpumask_clear_cpu(boot_cpuid, of_spin_mask);
-
        /* Non-lpar has additional take/give timebase */
        if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
                smp_ops->give_timebase = rtas_give_timebase;
index dcc6ac2d802637ab6e5fb9c004eaa69ba5e01479..7143793859fadf0cbc66c1b2119c5cbaee6368c8 100644 (file)
@@ -93,6 +93,7 @@ config S390
        select ARCH_INLINE_WRITE_UNLOCK_IRQ
        select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
        select ARCH_SAVE_PAGE_KEYS if HIBERNATION
+       select ARCH_USE_CMPXCHG_LOCKREF
        select ARCH_WANT_IPC_PARSE_VERSION
        select BUILDTIME_EXTABLE_SORT
        select CLONE_BACKWARDS2
@@ -102,7 +103,6 @@ config S390
        select GENERIC_TIME_VSYSCALL_OLD
        select HAVE_ALIGNED_STRUCT_PAGE if SLUB
        select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
-       select HAVE_ARCH_MUTEX_CPU_RELAX
        select HAVE_ARCH_SECCOMP_FILTER
        select HAVE_ARCH_TRACEHOOK
        select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT
index 688271f5f2e452b9951599550f33ed0ddcfe0a7c..458c1f7fbc1808d48982aa0c5fe89bfe3df2098c 100644 (file)
@@ -7,5 +7,3 @@
  */
 
 #include <asm-generic/mutex-dec.h>
-
-#define arch_mutex_cpu_relax() barrier()
index 0eb37505cab11c71f083ed508f02c98a72127e95..ca7821f07260301f26c2ff9314432b193ad8bebf 100644 (file)
@@ -198,6 +198,8 @@ static inline void cpu_relax(void)
        barrier();
 }
 
+#define arch_mutex_cpu_relax()  barrier()
+
 static inline void psw_set_key(unsigned int key)
 {
        asm volatile("spka 0(%0)" : : "d" (key));
index 701fe8c59e1f0e9efc302e711eef5bcfe3db479a..83e5d216105e86a2df2ab1367bcfc3fd1590542a 100644 (file)
@@ -44,6 +44,11 @@ extern void arch_spin_lock_wait_flags(arch_spinlock_t *, unsigned long flags);
 extern int arch_spin_trylock_retry(arch_spinlock_t *);
 extern void arch_spin_relax(arch_spinlock_t *lock);
 
+static inline int arch_spin_value_unlocked(arch_spinlock_t lock)
+{
+       return lock.owner_cpu == 0;
+}
+
 static inline void arch_spin_lock(arch_spinlock_t *lp)
 {
        int old;
index a1be70db75fec95d9cfa087008edf86a6baf7280..305f7ee1f382e60739464c6d0f3de98855d638ea 100644 (file)
@@ -2,6 +2,7 @@ menu "Machine selection"
 
 config SCORE
        def_bool y
+       select HAVE_GENERIC_HARDIRQS
        select GENERIC_IRQ_SHOW
        select GENERIC_IOMAP
        select GENERIC_ATOMIC64
@@ -110,3 +111,6 @@ source "security/Kconfig"
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
+
+config NO_IOMEM
+       def_bool y
index 974aefe861233b8615ed61253a6f7a1d4b21085c..9e3e060290e0895529c864d7e6892e0c47708f43 100644 (file)
@@ -20,8 +20,8 @@ cflags-y += -G0 -pipe -mel -mnhwloop -D__SCOREEL__ \
 #
 KBUILD_AFLAGS += $(cflags-y)
 KBUILD_CFLAGS += $(cflags-y)
-KBUILD_AFLAGS_MODULE += -mlong-calls
-KBUILD_CFLAGS_MODULE += -mlong-calls
+KBUILD_AFLAGS_MODULE +=
+KBUILD_CFLAGS_MODULE +=
 LDFLAGS += --oformat elf32-littlescore
 LDFLAGS_vmlinux        += -G0 -static -nostdlib
 
index f909ac3144a45a895751d038fbfea7495be59898..961bd64015a817b50452499d992ce23f14291247 100644 (file)
@@ -184,48 +184,57 @@ static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
                                __wsum sum)
 {
        __asm__ __volatile__(
-               ".set\tnoreorder\t\t\t# csum_ipv6_magic\n\t"
-               ".set\tnoat\n\t"
-               "addu\t%0, %5\t\t\t# proto (long in network byte order)\n\t"
-               "sltu\t$1, %0, %5\n\t"
-               "addu\t%0, $1\n\t"
-               "addu\t%0, %6\t\t\t# csum\n\t"
-               "sltu\t$1, %0, %6\n\t"
-               "lw\t%1, 0(%2)\t\t\t# four words source address\n\t"
-               "addu\t%0, $1\n\t"
-               "addu\t%0, %1\n\t"
-               "sltu\t$1, %0, %1\n\t"
-               "lw\t%1, 4(%2)\n\t"
-               "addu\t%0, $1\n\t"
-               "addu\t%0, %1\n\t"
-               "sltu\t$1, %0, %1\n\t"
-               "lw\t%1, 8(%2)\n\t"
-               "addu\t%0, $1\n\t"
-               "addu\t%0, %1\n\t"
-               "sltu\t$1, %0, %1\n\t"
-               "lw\t%1, 12(%2)\n\t"
-               "addu\t%0, $1\n\t"
-               "addu\t%0, %1\n\t"
-               "sltu\t$1, %0, %1\n\t"
-               "lw\t%1, 0(%3)\n\t"
-               "addu\t%0, $1\n\t"
-               "addu\t%0, %1\n\t"
-               "sltu\t$1, %0, %1\n\t"
-               "lw\t%1, 4(%3)\n\t"
-               "addu\t%0, $1\n\t"
-               "addu\t%0, %1\n\t"
-               "sltu\t$1, %0, %1\n\t"
-               "lw\t%1, 8(%3)\n\t"
-               "addu\t%0, $1\n\t"
-               "addu\t%0, %1\n\t"
-               "sltu\t$1, %0, %1\n\t"
-               "lw\t%1, 12(%3)\n\t"
-               "addu\t%0, $1\n\t"
-               "addu\t%0, %1\n\t"
-               "sltu\t$1, %0, %1\n\t"
-               "addu\t%0, $1\t\t\t# Add final carry\n\t"
-               ".set\tnoat\n\t"
-               ".set\tnoreorder"
+               ".set\tvolatile\t\t\t# csum_ipv6_magic\n\t"
+               "add\t%0, %0, %5\t\t\t# proto (long in network byte order)\n\t"
+               "cmp.c\t%5, %0\n\t"
+               "bleu 1f\n\t"
+               "addi\t%0, 0x1\n\t"
+               "1:add\t%0, %0, %6\t\t\t# csum\n\t"
+               "cmp.c\t%6, %0\n\t"
+               "lw\t%1, [%2, 0]\t\t\t# four words source address\n\t"
+               "bleu 1f\n\t"
+               "addi\t%0, 0x1\n\t"
+               "1:add\t%0, %0, %1\n\t"
+               "cmp.c\t%1, %0\n\t"
+               "1:lw\t%1, [%2, 4]\n\t"
+               "bleu 1f\n\t"
+               "addi\t%0, 0x1\n\t"
+               "1:add\t%0, %0, %1\n\t"
+               "cmp.c\t%1, %0\n\t"
+               "lw\t%1, [%2,8]\n\t"
+               "bleu 1f\n\t"
+               "addi\t%0, 0x1\n\t"
+               "1:add\t%0, %0, %1\n\t"
+               "cmp.c\t%1, %0\n\t"
+               "lw\t%1, [%2, 12]\n\t"
+               "bleu 1f\n\t"
+               "addi\t%0, 0x1\n\t"
+               "1:add\t%0, %0,%1\n\t"
+               "cmp.c\t%1, %0\n\t"
+               "lw\t%1, [%3, 0]\n\t"
+               "bleu 1f\n\t"
+               "addi\t%0, 0x1\n\t"
+               "1:add\t%0, %0, %1\n\t"
+               "cmp.c\t%1, %0\n\t"
+               "lw\t%1, [%3, 4]\n\t"
+               "bleu 1f\n\t"
+               "addi\t%0, 0x1\n\t"
+               "1:add\t%0, %0, %1\n\t"
+               "cmp.c\t%1, %0\n\t"
+               "lw\t%1, [%3, 8]\n\t"
+               "bleu 1f\n\t"
+               "addi\t%0, 0x1\n\t"
+               "1:add\t%0, %0, %1\n\t"
+               "cmp.c\t%1, %0\n\t"
+               "lw\t%1, [%3, 12]\n\t"
+               "bleu 1f\n\t"
+               "addi\t%0, 0x1\n\t"
+               "1:add\t%0, %0, %1\n\t"
+               "cmp.c\t%1, %0\n\t"
+               "bleu 1f\n\t"
+               "addi\t%0, 0x1\n\t"
+               "1:\n\t"
+               ".set\toptimize"
                : "=r" (sum), "=r" (proto)
                : "r" (saddr), "r" (daddr),
                  "0" (htonl(len)), "1" (htonl(proto)), "r" (sum));
index fbbfd7132e3b30b6d338fec1f9ea8f7572a76d7d..574c8827abe2381f2db65dfaf3a8f889cf52987b 100644 (file)
@@ -5,5 +5,4 @@
 
 #define virt_to_bus    virt_to_phys
 #define bus_to_virt    phys_to_virt
-
 #endif /* _ASM_SCORE_IO_H */
index 059a61b7071b2ab4d8e5ada5e9d1aa732b435206..716b3fd1d86397ea57389a106516eb12073dde43 100644 (file)
@@ -2,7 +2,7 @@
 #define _ASM_SCORE_PGALLOC_H
 
 #include <linux/mm.h>
-
+#include <linux/highmem.h>
 static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
        pte_t *pte)
 {
index 7234ed09b7b7ef5e815b749d8f364921a04b6500..befb87d30a89a0d9d21a774fb8d542963224a6ff 100644 (file)
@@ -264,7 +264,7 @@ resume_kernel:
        disable_irq
        lw      r8, [r28, TI_PRE_COUNT]
        cmpz.c  r8
-       bne     r8, restore_all
+       bne     restore_all
 need_resched:
        lw      r8, [r28, TI_FLAGS]
        andri.c r9, r8, _TIF_NEED_RESCHED
@@ -415,7 +415,7 @@ ENTRY(handle_sys)
        sw      r9, [r0, PT_EPC]
 
        cmpi.c  r27, __NR_syscalls      # check syscall number
-       bgeu    illegal_syscall
+       bcs     illegal_syscall
 
        slli    r8, r27, 2              # get syscall routine
        la      r11, sys_call_table
index f4c6d02421d3168cd8b17e87906490b214e7de96..a1519ad3d49d68e0e3202ecadb5b6e1b027a7df3 100644 (file)
@@ -78,8 +78,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        p->thread.reg0 = (unsigned long) childregs;
        if (unlikely(p->flags & PF_KTHREAD)) {
                memset(childregs, 0, sizeof(struct pt_regs));
-               p->thread->reg12 = usp;
-               p->thread->reg13 = arg;
+               p->thread.reg12 = usp;
+               p->thread.reg13 = arg;
                p->thread.reg3 = (unsigned long) ret_from_kernel_thread;
        } else {
                *childregs = *current_pt_regs();
index 2137ad6674388a8e920fba2d7b9fba0cf88512e6..78c4fdb91bc57a425e9fd5978260088ef5072d34 100644 (file)
@@ -506,12 +506,17 @@ config SUN_OPENPROMFS
          Only choose N if you know in advance that you will not need to modify
          OpenPROM settings on the running system.
 
-# Makefile helper
+# Makefile helpers
 config SPARC64_PCI
        bool
        default y
        depends on SPARC64 && PCI
 
+config SPARC64_PCI_MSI
+       bool
+       default y
+       depends on SPARC64_PCI && PCI_MSI
+
 endmenu
 
 menu "Executable file formats"
index e204f902e6c9f3088ef11ea8dd571c80ba48b7f4..7c90c50c200d307465c5f814c2b4256f1a01b016 100644 (file)
@@ -254,7 +254,7 @@ static int sun_fd_request_irq(void)
                once = 1;
 
                error = request_irq(FLOPPY_IRQ, sparc_floppy_irq,
-                                   IRQF_DISABLED, "floppy", NULL);
+                                   0, "floppy", NULL);
 
                return ((error == 0) ? 0 : -1);
        }
index d432fb20358e1785c3f6d6d2f0784580497a76ae..d15cc1794b0ec4890d3f6f717680b3673e76a0a9 100644 (file)
@@ -1,3 +1,4 @@
+
 #
 # Makefile for the linux kernel.
 #
@@ -99,7 +100,7 @@ obj-$(CONFIG_STACKTRACE)     += stacktrace.o
 obj-$(CONFIG_SPARC64_PCI)    += pci.o pci_common.o psycho_common.o
 obj-$(CONFIG_SPARC64_PCI)    += pci_psycho.o pci_sabre.o pci_schizo.o
 obj-$(CONFIG_SPARC64_PCI)    += pci_sun4v.o pci_sun4v_asm.o pci_fire.o
-obj-$(CONFIG_PCI_MSI)        += pci_msi.o
+obj-$(CONFIG_SPARC64_PCI_MSI) += pci_msi.o
 
 obj-$(CONFIG_COMPAT)         += sys32.o sys_sparc32.o signal32.o
 
index 62d6b153ffa2e82d895a4e81b51b2abe9490aee8..dff60abbea012f30a8b55221cc8d7a3a60a762ea 100644 (file)
@@ -849,9 +849,8 @@ void ldom_reboot(const char *boot_command)
        if (boot_command && strlen(boot_command)) {
                unsigned long len;
 
-               strcpy(full_boot_str, "boot ");
-               strlcpy(full_boot_str + strlen("boot "), boot_command,
-                       sizeof(full_boot_str + strlen("boot ")));
+               snprintf(full_boot_str, sizeof(full_boot_str), "boot %s",
+                        boot_command);
                len = strlen(full_boot_str);
 
                if (reboot_data_supported) {
index 54df554b82d98a684a3cbd7710ea10998e0d1722..e01d75d40329f010a1cc3c41020e100c6488e334 100644 (file)
@@ -1249,12 +1249,12 @@ int ldc_bind(struct ldc_channel *lp, const char *name)
        snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name);
        snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name);
 
-       err = request_irq(lp->cfg.rx_irq, ldc_rx, IRQF_DISABLED,
+       err = request_irq(lp->cfg.rx_irq, ldc_rx, 0,
                          lp->rx_irq_name, lp);
        if (err)
                return err;
 
-       err = request_irq(lp->cfg.tx_irq, ldc_tx, IRQF_DISABLED,
+       err = request_irq(lp->cfg.tx_irq, ldc_tx, 0,
                          lp->tx_irq_name, lp);
        if (err) {
                free_irq(lp->cfg.rx_irq, lp);
index 8a7cc663b3f85b479a14cdf03b3c757c948cc660..d45a2c48f1850d65fe01a0c23a91eea1115fc1dd 100644 (file)
@@ -361,7 +361,7 @@ config CMDLINE_OVERRIDE
 
 config VMALLOC_RESERVE
        hex
-       default 0x1000000
+       default 0x2000000
 
 config HARDWALL
        bool "Hardwall support to allow access to user dynamic network"
index 4f8f3d619c4a652b428029f0bc2c0362775d79dd..e19325c4c43168ace7298a123b0f0d210b25172b 100644 (file)
@@ -21,7 +21,7 @@ struct alloc_buffer_stacks_param {
        unsigned int flags;
 };
 
-int gxio_mpipe_alloc_buffer_stacks(gxio_mpipe_context_t * context,
+int gxio_mpipe_alloc_buffer_stacks(gxio_mpipe_context_t *context,
                                   unsigned int count, unsigned int first,
                                   unsigned int flags)
 {
@@ -45,7 +45,7 @@ struct init_buffer_stack_aux_param {
        unsigned int buffer_size_enum;
 };
 
-int gxio_mpipe_init_buffer_stack_aux(gxio_mpipe_context_t * context,
+int gxio_mpipe_init_buffer_stack_aux(gxio_mpipe_context_t *context,
                                     void *mem_va, size_t mem_size,
                                     unsigned int mem_flags, unsigned int stack,
                                     unsigned int buffer_size_enum)
@@ -80,7 +80,7 @@ struct alloc_notif_rings_param {
        unsigned int flags;
 };
 
-int gxio_mpipe_alloc_notif_rings(gxio_mpipe_context_t * context,
+int gxio_mpipe_alloc_notif_rings(gxio_mpipe_context_t *context,
                                 unsigned int count, unsigned int first,
                                 unsigned int flags)
 {
@@ -102,7 +102,7 @@ struct init_notif_ring_aux_param {
        unsigned int ring;
 };
 
-int gxio_mpipe_init_notif_ring_aux(gxio_mpipe_context_t * context, void *mem_va,
+int gxio_mpipe_init_notif_ring_aux(gxio_mpipe_context_t *context, void *mem_va,
                                   size_t mem_size, unsigned int mem_flags,
                                   unsigned int ring)
 {
@@ -133,7 +133,7 @@ struct request_notif_ring_interrupt_param {
        unsigned int ring;
 };
 
-int gxio_mpipe_request_notif_ring_interrupt(gxio_mpipe_context_t * context,
+int gxio_mpipe_request_notif_ring_interrupt(gxio_mpipe_context_t *context,
                                            int inter_x, int inter_y,
                                            int inter_ipi, int inter_event,
                                            unsigned int ring)
@@ -158,7 +158,7 @@ struct enable_notif_ring_interrupt_param {
        unsigned int ring;
 };
 
-int gxio_mpipe_enable_notif_ring_interrupt(gxio_mpipe_context_t * context,
+int gxio_mpipe_enable_notif_ring_interrupt(gxio_mpipe_context_t *context,
                                           unsigned int ring)
 {
        struct enable_notif_ring_interrupt_param temp;
@@ -179,7 +179,7 @@ struct alloc_notif_groups_param {
        unsigned int flags;
 };
 
-int gxio_mpipe_alloc_notif_groups(gxio_mpipe_context_t * context,
+int gxio_mpipe_alloc_notif_groups(gxio_mpipe_context_t *context,
                                  unsigned int count, unsigned int first,
                                  unsigned int flags)
 {
@@ -201,7 +201,7 @@ struct init_notif_group_param {
        gxio_mpipe_notif_group_bits_t bits;
 };
 
-int gxio_mpipe_init_notif_group(gxio_mpipe_context_t * context,
+int gxio_mpipe_init_notif_group(gxio_mpipe_context_t *context,
                                unsigned int group,
                                gxio_mpipe_notif_group_bits_t bits)
 {
@@ -223,7 +223,7 @@ struct alloc_buckets_param {
        unsigned int flags;
 };
 
-int gxio_mpipe_alloc_buckets(gxio_mpipe_context_t * context, unsigned int count,
+int gxio_mpipe_alloc_buckets(gxio_mpipe_context_t *context, unsigned int count,
                             unsigned int first, unsigned int flags)
 {
        struct alloc_buckets_param temp;
@@ -244,7 +244,7 @@ struct init_bucket_param {
        MPIPE_LBL_INIT_DAT_BSTS_TBL_t bucket_info;
 };
 
-int gxio_mpipe_init_bucket(gxio_mpipe_context_t * context, unsigned int bucket,
+int gxio_mpipe_init_bucket(gxio_mpipe_context_t *context, unsigned int bucket,
                           MPIPE_LBL_INIT_DAT_BSTS_TBL_t bucket_info)
 {
        struct init_bucket_param temp;
@@ -265,7 +265,7 @@ struct alloc_edma_rings_param {
        unsigned int flags;
 };
 
-int gxio_mpipe_alloc_edma_rings(gxio_mpipe_context_t * context,
+int gxio_mpipe_alloc_edma_rings(gxio_mpipe_context_t *context,
                                unsigned int count, unsigned int first,
                                unsigned int flags)
 {
@@ -288,7 +288,7 @@ struct init_edma_ring_aux_param {
        unsigned int channel;
 };
 
-int gxio_mpipe_init_edma_ring_aux(gxio_mpipe_context_t * context, void *mem_va,
+int gxio_mpipe_init_edma_ring_aux(gxio_mpipe_context_t *context, void *mem_va,
                                  size_t mem_size, unsigned int mem_flags,
                                  unsigned int ring, unsigned int channel)
 {
@@ -315,7 +315,7 @@ int gxio_mpipe_init_edma_ring_aux(gxio_mpipe_context_t * context, void *mem_va,
 EXPORT_SYMBOL(gxio_mpipe_init_edma_ring_aux);
 
 
-int gxio_mpipe_commit_rules(gxio_mpipe_context_t * context, const void *blob,
+int gxio_mpipe_commit_rules(gxio_mpipe_context_t *context, const void *blob,
                            size_t blob_size)
 {
        const void *params = blob;
@@ -332,7 +332,7 @@ struct register_client_memory_param {
        unsigned int flags;
 };
 
-int gxio_mpipe_register_client_memory(gxio_mpipe_context_t * context,
+int gxio_mpipe_register_client_memory(gxio_mpipe_context_t *context,
                                      unsigned int iotlb, HV_PTE pte,
                                      unsigned int flags)
 {
@@ -355,7 +355,7 @@ struct link_open_aux_param {
        unsigned int flags;
 };
 
-int gxio_mpipe_link_open_aux(gxio_mpipe_context_t * context,
+int gxio_mpipe_link_open_aux(gxio_mpipe_context_t *context,
                             _gxio_mpipe_link_name_t name, unsigned int flags)
 {
        struct link_open_aux_param temp;
@@ -374,7 +374,7 @@ struct link_close_aux_param {
        int mac;
 };
 
-int gxio_mpipe_link_close_aux(gxio_mpipe_context_t * context, int mac)
+int gxio_mpipe_link_close_aux(gxio_mpipe_context_t *context, int mac)
 {
        struct link_close_aux_param temp;
        struct link_close_aux_param *params = &temp;
@@ -393,7 +393,7 @@ struct link_set_attr_aux_param {
        int64_t val;
 };
 
-int gxio_mpipe_link_set_attr_aux(gxio_mpipe_context_t * context, int mac,
+int gxio_mpipe_link_set_attr_aux(gxio_mpipe_context_t *context, int mac,
                                 uint32_t attr, int64_t val)
 {
        struct link_set_attr_aux_param temp;
@@ -415,8 +415,8 @@ struct get_timestamp_aux_param {
        uint64_t cycles;
 };
 
-int gxio_mpipe_get_timestamp_aux(gxio_mpipe_context_t * context, uint64_t * sec,
-                                uint64_t * nsec, uint64_t * cycles)
+int gxio_mpipe_get_timestamp_aux(gxio_mpipe_context_t *context, uint64_t *sec,
+                                uint64_t *nsec, uint64_t *cycles)
 {
        int __result;
        struct get_timestamp_aux_param temp;
@@ -440,7 +440,7 @@ struct set_timestamp_aux_param {
        uint64_t cycles;
 };
 
-int gxio_mpipe_set_timestamp_aux(gxio_mpipe_context_t * context, uint64_t sec,
+int gxio_mpipe_set_timestamp_aux(gxio_mpipe_context_t *context, uint64_t sec,
                                 uint64_t nsec, uint64_t cycles)
 {
        struct set_timestamp_aux_param temp;
@@ -460,8 +460,7 @@ struct adjust_timestamp_aux_param {
        int64_t nsec;
 };
 
-int gxio_mpipe_adjust_timestamp_aux(gxio_mpipe_context_t * context,
-                                   int64_t nsec)
+int gxio_mpipe_adjust_timestamp_aux(gxio_mpipe_context_t *context, int64_t nsec)
 {
        struct adjust_timestamp_aux_param temp;
        struct adjust_timestamp_aux_param *params = &temp;
@@ -475,25 +474,6 @@ int gxio_mpipe_adjust_timestamp_aux(gxio_mpipe_context_t * context,
 
 EXPORT_SYMBOL(gxio_mpipe_adjust_timestamp_aux);
 
-struct adjust_timestamp_freq_param {
-       int32_t ppb;
-};
-
-int gxio_mpipe_adjust_timestamp_freq(gxio_mpipe_context_t * context,
-                                    int32_t ppb)
-{
-       struct adjust_timestamp_freq_param temp;
-       struct adjust_timestamp_freq_param *params = &temp;
-
-       params->ppb = ppb;
-
-       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
-                            sizeof(*params),
-                            GXIO_MPIPE_OP_ADJUST_TIMESTAMP_FREQ);
-}
-
-EXPORT_SYMBOL(gxio_mpipe_adjust_timestamp_freq);
-
 struct config_edma_ring_blks_param {
        unsigned int ering;
        unsigned int max_blks;
@@ -501,7 +481,7 @@ struct config_edma_ring_blks_param {
        unsigned int db;
 };
 
-int gxio_mpipe_config_edma_ring_blks(gxio_mpipe_context_t * context,
+int gxio_mpipe_config_edma_ring_blks(gxio_mpipe_context_t *context,
                                     unsigned int ering, unsigned int max_blks,
                                     unsigned int min_snf_blks, unsigned int db)
 {
@@ -520,11 +500,29 @@ int gxio_mpipe_config_edma_ring_blks(gxio_mpipe_context_t * context,
 
 EXPORT_SYMBOL(gxio_mpipe_config_edma_ring_blks);
 
+struct adjust_timestamp_freq_param {
+       int32_t ppb;
+};
+
+int gxio_mpipe_adjust_timestamp_freq(gxio_mpipe_context_t *context, int32_t ppb)
+{
+       struct adjust_timestamp_freq_param temp;
+       struct adjust_timestamp_freq_param *params = &temp;
+
+       params->ppb = ppb;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params),
+                            GXIO_MPIPE_OP_ADJUST_TIMESTAMP_FREQ);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_adjust_timestamp_freq);
+
 struct arm_pollfd_param {
        union iorpc_pollfd pollfd;
 };
 
-int gxio_mpipe_arm_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie)
+int gxio_mpipe_arm_pollfd(gxio_mpipe_context_t *context, int pollfd_cookie)
 {
        struct arm_pollfd_param temp;
        struct arm_pollfd_param *params = &temp;
@@ -541,7 +539,7 @@ struct close_pollfd_param {
        union iorpc_pollfd pollfd;
 };
 
-int gxio_mpipe_close_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie)
+int gxio_mpipe_close_pollfd(gxio_mpipe_context_t *context, int pollfd_cookie)
 {
        struct close_pollfd_param temp;
        struct close_pollfd_param *params = &temp;
@@ -558,7 +556,7 @@ struct get_mmio_base_param {
        HV_PTE base;
 };
 
-int gxio_mpipe_get_mmio_base(gxio_mpipe_context_t * context, HV_PTE *base)
+int gxio_mpipe_get_mmio_base(gxio_mpipe_context_t *context, HV_PTE *base)
 {
        int __result;
        struct get_mmio_base_param temp;
@@ -579,7 +577,7 @@ struct check_mmio_offset_param {
        unsigned long size;
 };
 
-int gxio_mpipe_check_mmio_offset(gxio_mpipe_context_t * context,
+int gxio_mpipe_check_mmio_offset(gxio_mpipe_context_t *context,
                                 unsigned long offset, unsigned long size)
 {
        struct check_mmio_offset_param temp;
index 64883aabeb9c19d2ce3d5e72f4c4040813c33e83..77019c6e9b4ab1178cafff23e6b33a9780934545 100644 (file)
 /* This file is machine-generated; DO NOT EDIT! */
 #include "gxio/iorpc_mpipe_info.h"
 
-
 struct instance_aux_param {
        _gxio_mpipe_link_name_t name;
 };
 
-int gxio_mpipe_info_instance_aux(gxio_mpipe_info_context_t * context,
+int gxio_mpipe_info_instance_aux(gxio_mpipe_info_context_t *context,
                                 _gxio_mpipe_link_name_t name)
 {
        struct instance_aux_param temp;
@@ -39,10 +38,10 @@ struct enumerate_aux_param {
        _gxio_mpipe_link_mac_t mac;
 };
 
-int gxio_mpipe_info_enumerate_aux(gxio_mpipe_info_context_t * context,
+int gxio_mpipe_info_enumerate_aux(gxio_mpipe_info_context_t *context,
                                  unsigned int idx,
-                                 _gxio_mpipe_link_name_t * name,
-                                 _gxio_mpipe_link_mac_t * mac)
+                                 _gxio_mpipe_link_name_t *name,
+                                 _gxio_mpipe_link_mac_t *mac)
 {
        int __result;
        struct enumerate_aux_param temp;
@@ -50,7 +49,7 @@ int gxio_mpipe_info_enumerate_aux(gxio_mpipe_info_context_t * context,
 
        __result =
            hv_dev_pread(context->fd, 0, (HV_VirtAddr) params, sizeof(*params),
-                        (((uint64_t) idx << 32) |
+                        (((uint64_t)idx << 32) |
                          GXIO_MPIPE_INFO_OP_ENUMERATE_AUX));
        *name = params->name;
        *mac = params->mac;
@@ -64,7 +63,7 @@ struct get_mmio_base_param {
        HV_PTE base;
 };
 
-int gxio_mpipe_info_get_mmio_base(gxio_mpipe_info_context_t * context,
+int gxio_mpipe_info_get_mmio_base(gxio_mpipe_info_context_t *context,
                                  HV_PTE *base)
 {
        int __result;
@@ -86,7 +85,7 @@ struct check_mmio_offset_param {
        unsigned long size;
 };
 
-int gxio_mpipe_info_check_mmio_offset(gxio_mpipe_info_context_t * context,
+int gxio_mpipe_info_check_mmio_offset(gxio_mpipe_info_context_t *context,
                                      unsigned long offset, unsigned long size)
 {
        struct check_mmio_offset_param temp;
index da6e18e049c35a5093d90522993cfdcf75dd2b76..1d3cedb9aeb42714d018f9b8e4aef1fcc6b908e3 100644 (file)
@@ -21,7 +21,7 @@ struct alloc_asids_param {
        unsigned int flags;
 };
 
-int gxio_trio_alloc_asids(gxio_trio_context_t * context, unsigned int count,
+int gxio_trio_alloc_asids(gxio_trio_context_t *context, unsigned int count,
                          unsigned int first, unsigned int flags)
 {
        struct alloc_asids_param temp;
@@ -44,7 +44,7 @@ struct alloc_memory_maps_param {
        unsigned int flags;
 };
 
-int gxio_trio_alloc_memory_maps(gxio_trio_context_t * context,
+int gxio_trio_alloc_memory_maps(gxio_trio_context_t *context,
                                unsigned int count, unsigned int first,
                                unsigned int flags)
 {
@@ -67,7 +67,7 @@ struct alloc_scatter_queues_param {
        unsigned int flags;
 };
 
-int gxio_trio_alloc_scatter_queues(gxio_trio_context_t * context,
+int gxio_trio_alloc_scatter_queues(gxio_trio_context_t *context,
                                   unsigned int count, unsigned int first,
                                   unsigned int flags)
 {
@@ -91,7 +91,7 @@ struct alloc_pio_regions_param {
        unsigned int flags;
 };
 
-int gxio_trio_alloc_pio_regions(gxio_trio_context_t * context,
+int gxio_trio_alloc_pio_regions(gxio_trio_context_t *context,
                                unsigned int count, unsigned int first,
                                unsigned int flags)
 {
@@ -115,7 +115,7 @@ struct init_pio_region_aux_param {
        unsigned int flags;
 };
 
-int gxio_trio_init_pio_region_aux(gxio_trio_context_t * context,
+int gxio_trio_init_pio_region_aux(gxio_trio_context_t *context,
                                  unsigned int pio_region, unsigned int mac,
                                  uint32_t bus_address_hi, unsigned int flags)
 {
@@ -145,7 +145,7 @@ struct init_memory_map_mmu_aux_param {
        unsigned int order_mode;
 };
 
-int gxio_trio_init_memory_map_mmu_aux(gxio_trio_context_t * context,
+int gxio_trio_init_memory_map_mmu_aux(gxio_trio_context_t *context,
                                      unsigned int map, unsigned long va,
                                      uint64_t size, unsigned int asid,
                                      unsigned int mac, uint64_t bus_address,
@@ -175,7 +175,7 @@ struct get_port_property_param {
        struct pcie_trio_ports_property trio_ports;
 };
 
-int gxio_trio_get_port_property(gxio_trio_context_t * context,
+int gxio_trio_get_port_property(gxio_trio_context_t *context,
                                struct pcie_trio_ports_property *trio_ports)
 {
        int __result;
@@ -198,7 +198,7 @@ struct config_legacy_intr_param {
        unsigned int intx;
 };
 
-int gxio_trio_config_legacy_intr(gxio_trio_context_t * context, int inter_x,
+int gxio_trio_config_legacy_intr(gxio_trio_context_t *context, int inter_x,
                                 int inter_y, int inter_ipi, int inter_event,
                                 unsigned int mac, unsigned int intx)
 {
@@ -227,7 +227,7 @@ struct config_msi_intr_param {
        unsigned int asid;
 };
 
-int gxio_trio_config_msi_intr(gxio_trio_context_t * context, int inter_x,
+int gxio_trio_config_msi_intr(gxio_trio_context_t *context, int inter_x,
                              int inter_y, int inter_ipi, int inter_event,
                              unsigned int mac, unsigned int mem_map,
                              uint64_t mem_map_base, uint64_t mem_map_limit,
@@ -259,7 +259,7 @@ struct set_mps_mrs_param {
        unsigned int mac;
 };
 
-int gxio_trio_set_mps_mrs(gxio_trio_context_t * context, uint16_t mps,
+int gxio_trio_set_mps_mrs(gxio_trio_context_t *context, uint16_t mps,
                          uint16_t mrs, unsigned int mac)
 {
        struct set_mps_mrs_param temp;
@@ -279,7 +279,7 @@ struct force_rc_link_up_param {
        unsigned int mac;
 };
 
-int gxio_trio_force_rc_link_up(gxio_trio_context_t * context, unsigned int mac)
+int gxio_trio_force_rc_link_up(gxio_trio_context_t *context, unsigned int mac)
 {
        struct force_rc_link_up_param temp;
        struct force_rc_link_up_param *params = &temp;
@@ -296,7 +296,7 @@ struct force_ep_link_up_param {
        unsigned int mac;
 };
 
-int gxio_trio_force_ep_link_up(gxio_trio_context_t * context, unsigned int mac)
+int gxio_trio_force_ep_link_up(gxio_trio_context_t *context, unsigned int mac)
 {
        struct force_ep_link_up_param temp;
        struct force_ep_link_up_param *params = &temp;
@@ -313,7 +313,7 @@ struct get_mmio_base_param {
        HV_PTE base;
 };
 
-int gxio_trio_get_mmio_base(gxio_trio_context_t * context, HV_PTE *base)
+int gxio_trio_get_mmio_base(gxio_trio_context_t *context, HV_PTE *base)
 {
        int __result;
        struct get_mmio_base_param temp;
@@ -334,7 +334,7 @@ struct check_mmio_offset_param {
        unsigned long size;
 };
 
-int gxio_trio_check_mmio_offset(gxio_trio_context_t * context,
+int gxio_trio_check_mmio_offset(gxio_trio_context_t *context,
                                unsigned long offset, unsigned long size)
 {
        struct check_mmio_offset_param temp;
index cf3c3cc122048ddb1d93390e9c864849abfc706a..9c820073bfc01bcdc92c946e904c1a600eb801a8 100644 (file)
@@ -19,7 +19,7 @@ struct cfg_interrupt_param {
        union iorpc_interrupt interrupt;
 };
 
-int gxio_usb_host_cfg_interrupt(gxio_usb_host_context_t * context, int inter_x,
+int gxio_usb_host_cfg_interrupt(gxio_usb_host_context_t *context, int inter_x,
                                int inter_y, int inter_ipi, int inter_event)
 {
        struct cfg_interrupt_param temp;
@@ -41,7 +41,7 @@ struct register_client_memory_param {
        unsigned int flags;
 };
 
-int gxio_usb_host_register_client_memory(gxio_usb_host_context_t * context,
+int gxio_usb_host_register_client_memory(gxio_usb_host_context_t *context,
                                         HV_PTE pte, unsigned int flags)
 {
        struct register_client_memory_param temp;
@@ -61,7 +61,7 @@ struct get_mmio_base_param {
        HV_PTE base;
 };
 
-int gxio_usb_host_get_mmio_base(gxio_usb_host_context_t * context, HV_PTE *base)
+int gxio_usb_host_get_mmio_base(gxio_usb_host_context_t *context, HV_PTE *base)
 {
        int __result;
        struct get_mmio_base_param temp;
@@ -82,7 +82,7 @@ struct check_mmio_offset_param {
        unsigned long size;
 };
 
-int gxio_usb_host_check_mmio_offset(gxio_usb_host_context_t * context,
+int gxio_usb_host_check_mmio_offset(gxio_usb_host_context_t *context,
                                    unsigned long offset, unsigned long size)
 {
        struct check_mmio_offset_param temp;
index 66b002f54ecc1cfa157c9aa2989a074876a96be1..785afad7922eed1d1837a36d488ca7a30d399022 100644 (file)
@@ -26,7 +26,7 @@
 #include <gxio/kiorpc.h>
 #include <gxio/usb_host.h>
 
-int gxio_usb_host_init(gxio_usb_host_context_t * context, int usb_index,
+int gxio_usb_host_init(gxio_usb_host_context_t *context, int usb_index,
                       int is_ehci)
 {
        char file[32];
@@ -63,7 +63,7 @@ int gxio_usb_host_init(gxio_usb_host_context_t * context, int usb_index,
 
 EXPORT_SYMBOL_GPL(gxio_usb_host_init);
 
-int gxio_usb_host_destroy(gxio_usb_host_context_t * context)
+int gxio_usb_host_destroy(gxio_usb_host_context_t *context)
 {
        iounmap((void __force __iomem *)(context->mmio_base));
        hv_dev_close(context->fd);
@@ -76,14 +76,14 @@ int gxio_usb_host_destroy(gxio_usb_host_context_t * context)
 
 EXPORT_SYMBOL_GPL(gxio_usb_host_destroy);
 
-void *gxio_usb_host_get_reg_start(gxio_usb_host_context_t * context)
+void *gxio_usb_host_get_reg_start(gxio_usb_host_context_t *context)
 {
        return context->mmio_base;
 }
 
 EXPORT_SYMBOL_GPL(gxio_usb_host_get_reg_start);
 
-size_t gxio_usb_host_get_reg_len(gxio_usb_host_context_t * context)
+size_t gxio_usb_host_get_reg_len(gxio_usb_host_context_t *context)
 {
        return HV_USB_HOST_MMIO_SIZE;
 }
index 8a33912fd6cc941053bcbab6d1103cb6a8eec203..904538e754d8ad62888a15e3963f00a2963416eb 100644 (file)
@@ -176,7 +176,18 @@ typedef union
      */
     uint_reg_t stack_idx    : 5;
     /* Reserved. */
-    uint_reg_t __reserved_2 : 5;
+    uint_reg_t __reserved_2 : 3;
+    /*
+     * Instance ID.  For devices that support automatic buffer return between
+     * mPIPE instances, this field indicates the buffer owner.  If the INST
+     * field does not match the mPIPE's instance number when a packet is
+     * egressed, buffers with HWB set will be returned to the other mPIPE
+     * instance.  Note that not all devices support multi-mPIPE buffer
+     * return.  The MPIPE_EDMA_INFO.REMOTE_BUFF_RTN_SUPPORT bit indicates
+     * whether the INST field in the buffer descriptor is populated by iDMA
+     * hardware. This field is ignored on writes.
+     */
+    uint_reg_t inst         : 2;
     /*
      * Reads as one to indicate that this is a hardware managed buffer.
      * Ignored on writes since all buffers on a given stack are the same size.
@@ -205,7 +216,8 @@ typedef union
     uint_reg_t c            : 2;
     uint_reg_t size         : 3;
     uint_reg_t hwb          : 1;
-    uint_reg_t __reserved_2 : 5;
+    uint_reg_t inst         : 2;
+    uint_reg_t __reserved_2 : 3;
     uint_reg_t stack_idx    : 5;
     uint_reg_t __reserved_1 : 6;
     int_reg_t va           : 35;
@@ -231,9 +243,9 @@ typedef union
     /* Reserved. */
     uint_reg_t __reserved_0 : 3;
     /* eDMA ring being accessed */
-    uint_reg_t ring         : 5;
+    uint_reg_t ring         : 6;
     /* Reserved. */
-    uint_reg_t __reserved_1 : 18;
+    uint_reg_t __reserved_1 : 17;
     /*
      * This field of the address selects the region (address space) to be
      * accessed.  For the egress DMA post region, this field must be 5.
@@ -250,8 +262,8 @@ typedef union
     uint_reg_t svc_dom      : 5;
     uint_reg_t __reserved_2 : 6;
     uint_reg_t region       : 3;
-    uint_reg_t __reserved_1 : 18;
-    uint_reg_t ring         : 5;
+    uint_reg_t __reserved_1 : 17;
+    uint_reg_t ring         : 6;
     uint_reg_t __reserved_0 : 3;
 #endif
   };
index 410a0400e0558d50586118cbbbe273cfac2a4b58..84022ac5fe8287bf7ef7629643b388a33cdfb9c3 100644 (file)
 #ifndef __ARCH_MPIPE_CONSTANTS_H__
 #define __ARCH_MPIPE_CONSTANTS_H__
 
-#define MPIPE_NUM_CLASSIFIERS 10
+#define MPIPE_NUM_CLASSIFIERS 16
 #define MPIPE_CLS_MHZ 1200
 
-#define MPIPE_NUM_EDMA_RINGS 32
+#define MPIPE_NUM_EDMA_RINGS 64
 
 #define MPIPE_NUM_SGMII_MACS 16
-#define MPIPE_NUM_XAUI_MACS 4
+#define MPIPE_NUM_XAUI_MACS 16
 #define MPIPE_NUM_LOOPBACK_CHANNELS 4
 #define MPIPE_NUM_NON_LB_CHANNELS 28
 
index f2e9e122818d09d6e5a5df9fd100576487591c59..13b3c4300e500f97f80ab1d801c6a2d5b98c5eea 100644 (file)
@@ -44,8 +44,14 @@ typedef union
      * descriptors toggles each time the ring tail pointer wraps.
      */
     uint_reg_t gen        : 1;
+    /**
+     * For devices with EDMA reorder support, this field allows the
+     * descriptor to select the egress FIFO.  The associated DMA ring must
+     * have ALLOW_EFIFO_SEL enabled.
+     */
+    uint_reg_t efifo_sel  : 6;
     /** Reserved.  Must be zero. */
-    uint_reg_t r0         : 7;
+    uint_reg_t r0         : 1;
     /** Checksum generation enabled for this transfer. */
     uint_reg_t csum       : 1;
     /**
@@ -110,7 +116,8 @@ typedef union
     uint_reg_t notif      : 1;
     uint_reg_t ns         : 1;
     uint_reg_t csum       : 1;
-    uint_reg_t r0         : 7;
+    uint_reg_t r0         : 1;
+    uint_reg_t efifo_sel  : 6;
     uint_reg_t gen        : 1;
 #endif
 
@@ -126,14 +133,16 @@ typedef union
     /** Reserved. */
     uint_reg_t __reserved_1 : 3;
     /**
-     * Instance ID.  For devices that support more than one mPIPE instance,
-     * this field indicates the buffer owner.  If the INST field does not
-     * match the mPIPE's instance number when a packet is egressed, buffers
-     * with HWB set will be returned to the other mPIPE instance.
+     * Instance ID.  For devices that support automatic buffer return between
+     * mPIPE instances, this field indicates the buffer owner.  If the INST
+     * field does not match the mPIPE's instance number when a packet is
+     * egressed, buffers with HWB set will be returned to the other mPIPE
+     * instance.  Note that not all devices support multi-mPIPE buffer
+     * return.  The MPIPE_EDMA_INFO.REMOTE_BUFF_RTN_SUPPORT bit indicates
+     * whether the INST field in the buffer descriptor is populated by iDMA
+     * hardware.
      */
-    uint_reg_t inst         : 1;
-    /** Reserved. */
-    uint_reg_t __reserved_2 : 1;
+    uint_reg_t inst         : 2;
     /**
      * Always set to one by hardware in iDMA packet descriptors.  For eDMA,
      * indicates whether the buffer will be released to the buffer stack
@@ -166,8 +175,7 @@ typedef union
     uint_reg_t c            : 2;
     uint_reg_t size         : 3;
     uint_reg_t hwb          : 1;
-    uint_reg_t __reserved_2 : 1;
-    uint_reg_t inst         : 1;
+    uint_reg_t inst         : 2;
     uint_reg_t __reserved_1 : 3;
     uint_reg_t stack_idx    : 5;
     uint_reg_t __reserved_0 : 6;
@@ -408,7 +416,10 @@ typedef union
     /**
      * Sequence number applied when packet is distributed.   Classifier
      * selects which sequence number is to be applied by writing the 13-bit
-     * SQN-selector into this field.
+     * SQN-selector into this field.  For devices that support EXT_SQN (as
+     * indicated in IDMA_INFO.EXT_SQN_SUPPORT), the GP_SQN can be extended to
+     * 32-bits via the IDMA_CTL.EXT_SQN register.  In this case the
+     * PACKET_SQN will be reduced to 32 bits.
      */
     uint_reg_t gp_sqn     : 16;
     /**
@@ -451,14 +462,16 @@ typedef union
     /** Reserved. */
     uint_reg_t __reserved_5 : 3;
     /**
-     * Instance ID.  For devices that support more than one mPIPE instance,
-     * this field indicates the buffer owner.  If the INST field does not
-     * match the mPIPE's instance number when a packet is egressed, buffers
-     * with HWB set will be returned to the other mPIPE instance.
+     * Instance ID.  For devices that support automatic buffer return between
+     * mPIPE instances, this field indicates the buffer owner.  If the INST
+     * field does not match the mPIPE's instance number when a packet is
+     * egressed, buffers with HWB set will be returned to the other mPIPE
+     * instance.  Note that not all devices support multi-mPIPE buffer
+     * return.  The MPIPE_EDMA_INFO.REMOTE_BUFF_RTN_SUPPORT bit indicates
+     * whether the INST field in the buffer descriptor is populated by iDMA
+     * hardware.
      */
-    uint_reg_t inst         : 1;
-    /** Reserved. */
-    uint_reg_t __reserved_6 : 1;
+    uint_reg_t inst         : 2;
     /**
      * Always set to one by hardware in iDMA packet descriptors.  For eDMA,
      * indicates whether the buffer will be released to the buffer stack
@@ -491,8 +504,7 @@ typedef union
     uint_reg_t c            : 2;
     uint_reg_t size         : 3;
     uint_reg_t hwb          : 1;
-    uint_reg_t __reserved_6 : 1;
-    uint_reg_t inst         : 1;
+    uint_reg_t inst         : 2;
     uint_reg_t __reserved_5 : 3;
     uint_reg_t stack_idx    : 5;
     uint_reg_t __reserved_4 : 6;
index 628b045436b8969e6287fd401e13e35aa06b9e7e..85647e91a4584c0db815bebc1cbb2fa85fce71d0 100644 (file)
 #ifndef __ARCH_TRIO_CONSTANTS_H__
 #define __ARCH_TRIO_CONSTANTS_H__
 
-#define TRIO_NUM_ASIDS 16
+#define TRIO_NUM_ASIDS 32
 #define TRIO_NUM_TLBS_PER_ASID 16
 
 #define TRIO_NUM_TPIO_REGIONS 8
 #define TRIO_LOG2_NUM_TPIO_REGIONS 3
 
-#define TRIO_NUM_MAP_MEM_REGIONS 16
-#define TRIO_LOG2_NUM_MAP_MEM_REGIONS 4
+#define TRIO_NUM_MAP_MEM_REGIONS 32
+#define TRIO_LOG2_NUM_MAP_MEM_REGIONS 5
 #define TRIO_NUM_MAP_SQ_REGIONS 8
 #define TRIO_LOG2_NUM_MAP_SQ_REGIONS 3
 
 #define TRIO_LOG2_NUM_SQ_FIFO_ENTRIES 6
 
-#define TRIO_NUM_PUSH_DMA_RINGS 32
+#define TRIO_NUM_PUSH_DMA_RINGS 64
 
-#define TRIO_NUM_PULL_DMA_RINGS 32
+#define TRIO_NUM_PULL_DMA_RINGS 64
 
 #endif /* __ARCH_TRIO_CONSTANTS_H__ */
index 6346888f7bdc9359b38ee17104385adb9e501856..67276800861833f674422a10cf47440f7864af3b 100644 (file)
@@ -182,10 +182,9 @@ static inline __attribute_const__ int get_order(unsigned long size)
 
 #define PAGE_OFFSET            (-(_AC(1, UL) << (MAX_VA_WIDTH - 1)))
 #define KERNEL_HIGH_VADDR      _AC(0xfffffff800000000, UL)  /* high 32GB */
-#define FIXADDR_BASE           (KERNEL_HIGH_VADDR - 0x400000000) /* 4 GB */
-#define FIXADDR_TOP            (KERNEL_HIGH_VADDR - 0x300000000) /* 4 GB */
+#define FIXADDR_BASE           (KERNEL_HIGH_VADDR - 0x300000000) /* 4 GB */
+#define FIXADDR_TOP            (KERNEL_HIGH_VADDR - 0x200000000) /* 4 GB */
 #define _VMALLOC_START         FIXADDR_TOP
-#define HUGE_VMAP_BASE         (KERNEL_HIGH_VADDR - 0x200000000) /* 4 GB */
 #define MEM_SV_START           (KERNEL_HIGH_VADDR - 0x100000000) /* 256 MB */
 #define MEM_MODULE_START       (MEM_SV_START + (256*1024*1024)) /* 256 MB */
 #define MEM_MODULE_END         (MEM_MODULE_START + (256*1024*1024))
index 63142ab3b3dd8337bf1b6cc2c165af65fc85181a..d26a42279036837b760ea4b93593b45fe4394f83 100644 (file)
 #define PKMAP_BASE   ((FIXADDR_BOOT_START - PAGE_SIZE*LAST_PKMAP) & PGDIR_MASK)
 
 #ifdef CONFIG_HIGHMEM
-# define __VMAPPING_END        (PKMAP_BASE & ~(HPAGE_SIZE-1))
+# define _VMALLOC_END  (PKMAP_BASE & ~(HPAGE_SIZE-1))
 #else
-# define __VMAPPING_END        (FIXADDR_START & ~(HPAGE_SIZE-1))
-#endif
-
-#ifdef CONFIG_HUGEVMAP
-#define HUGE_VMAP_END  __VMAPPING_END
-#define HUGE_VMAP_BASE (HUGE_VMAP_END - CONFIG_NR_HUGE_VMAPS * HPAGE_SIZE)
-#define _VMALLOC_END   HUGE_VMAP_BASE
-#else
-#define _VMALLOC_END   __VMAPPING_END
+# define _VMALLOC_END  (FIXADDR_START & ~(HPAGE_SIZE-1))
 #endif
 
 /*
index 3421177f737002ee8c8addf515e30615729d08b5..2c8a9cd102d359f8a8ec5eb1cf4c515e7ad567ce 100644 (file)
  * memory allocation code).  The vmalloc code puts in an internal
  * guard page between each allocation.
  */
-#define _VMALLOC_END   HUGE_VMAP_BASE
+#define _VMALLOC_END   MEM_SV_START
 #define VMALLOC_END    _VMALLOC_END
 #define VMALLOC_START  _VMALLOC_START
 
-#define HUGE_VMAP_END  (HUGE_VMAP_BASE + PGDIR_SIZE)
-
 #ifndef __ASSEMBLY__
 
 /* We have no pud since we are a three-level page table. */
index fdd07f88cfd7124458a4d31fb1a098764e15bb9a..4cda03de734f5162bc43359483ce4eeace9ea1dd 100644 (file)
 #define GXIO_MPIPE_OP_GET_MMIO_BASE    IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000)
 #define GXIO_MPIPE_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001)
 
-int gxio_mpipe_alloc_buffer_stacks(gxio_mpipe_context_t * context,
+int gxio_mpipe_alloc_buffer_stacks(gxio_mpipe_context_t *context,
                                   unsigned int count, unsigned int first,
                                   unsigned int flags);
 
-int gxio_mpipe_init_buffer_stack_aux(gxio_mpipe_context_t * context,
+int gxio_mpipe_init_buffer_stack_aux(gxio_mpipe_context_t *context,
                                     void *mem_va, size_t mem_size,
                                     unsigned int mem_flags, unsigned int stack,
                                     unsigned int buffer_size_enum);
 
 
-int gxio_mpipe_alloc_notif_rings(gxio_mpipe_context_t * context,
+int gxio_mpipe_alloc_notif_rings(gxio_mpipe_context_t *context,
                                 unsigned int count, unsigned int first,
                                 unsigned int flags);
 
-int gxio_mpipe_init_notif_ring_aux(gxio_mpipe_context_t * context, void *mem_va,
+int gxio_mpipe_init_notif_ring_aux(gxio_mpipe_context_t *context, void *mem_va,
                                   size_t mem_size, unsigned int mem_flags,
                                   unsigned int ring);
 
-int gxio_mpipe_request_notif_ring_interrupt(gxio_mpipe_context_t * context,
+int gxio_mpipe_request_notif_ring_interrupt(gxio_mpipe_context_t *context,
                                            int inter_x, int inter_y,
                                            int inter_ipi, int inter_event,
                                            unsigned int ring);
 
-int gxio_mpipe_enable_notif_ring_interrupt(gxio_mpipe_context_t * context,
+int gxio_mpipe_enable_notif_ring_interrupt(gxio_mpipe_context_t *context,
                                           unsigned int ring);
 
-int gxio_mpipe_alloc_notif_groups(gxio_mpipe_context_t * context,
+int gxio_mpipe_alloc_notif_groups(gxio_mpipe_context_t *context,
                                  unsigned int count, unsigned int first,
                                  unsigned int flags);
 
-int gxio_mpipe_init_notif_group(gxio_mpipe_context_t * context,
+int gxio_mpipe_init_notif_group(gxio_mpipe_context_t *context,
                                unsigned int group,
                                gxio_mpipe_notif_group_bits_t bits);
 
-int gxio_mpipe_alloc_buckets(gxio_mpipe_context_t * context, unsigned int count,
+int gxio_mpipe_alloc_buckets(gxio_mpipe_context_t *context, unsigned int count,
                             unsigned int first, unsigned int flags);
 
-int gxio_mpipe_init_bucket(gxio_mpipe_context_t * context, unsigned int bucket,
+int gxio_mpipe_init_bucket(gxio_mpipe_context_t *context, unsigned int bucket,
                           MPIPE_LBL_INIT_DAT_BSTS_TBL_t bucket_info);
 
-int gxio_mpipe_alloc_edma_rings(gxio_mpipe_context_t * context,
+int gxio_mpipe_alloc_edma_rings(gxio_mpipe_context_t *context,
                                unsigned int count, unsigned int first,
                                unsigned int flags);
 
-int gxio_mpipe_init_edma_ring_aux(gxio_mpipe_context_t * context, void *mem_va,
+int gxio_mpipe_init_edma_ring_aux(gxio_mpipe_context_t *context, void *mem_va,
                                  size_t mem_size, unsigned int mem_flags,
                                  unsigned int ring, unsigned int channel);
 
 
-int gxio_mpipe_commit_rules(gxio_mpipe_context_t * context, const void *blob,
+int gxio_mpipe_commit_rules(gxio_mpipe_context_t *context, const void *blob,
                            size_t blob_size);
 
-int gxio_mpipe_register_client_memory(gxio_mpipe_context_t * context,
+int gxio_mpipe_register_client_memory(gxio_mpipe_context_t *context,
                                      unsigned int iotlb, HV_PTE pte,
                                      unsigned int flags);
 
-int gxio_mpipe_link_open_aux(gxio_mpipe_context_t * context,
+int gxio_mpipe_link_open_aux(gxio_mpipe_context_t *context,
                             _gxio_mpipe_link_name_t name, unsigned int flags);
 
-int gxio_mpipe_link_close_aux(gxio_mpipe_context_t * context, int mac);
+int gxio_mpipe_link_close_aux(gxio_mpipe_context_t *context, int mac);
 
-int gxio_mpipe_link_set_attr_aux(gxio_mpipe_context_t * context, int mac,
+int gxio_mpipe_link_set_attr_aux(gxio_mpipe_context_t *context, int mac,
                                 uint32_t attr, int64_t val);
 
-int gxio_mpipe_get_timestamp_aux(gxio_mpipe_context_t * context, uint64_t * sec,
-                                uint64_t * nsec, uint64_t * cycles);
+int gxio_mpipe_get_timestamp_aux(gxio_mpipe_context_t *context, uint64_t *sec,
+                                uint64_t *nsec, uint64_t *cycles);
 
-int gxio_mpipe_set_timestamp_aux(gxio_mpipe_context_t * context, uint64_t sec,
+int gxio_mpipe_set_timestamp_aux(gxio_mpipe_context_t *context, uint64_t sec,
                                 uint64_t nsec, uint64_t cycles);
 
-int gxio_mpipe_adjust_timestamp_aux(gxio_mpipe_context_t * context,
+int gxio_mpipe_adjust_timestamp_aux(gxio_mpipe_context_t *context,
                                    int64_t nsec);
 
-int gxio_mpipe_adjust_timestamp_freq(gxio_mpipe_context_t * context,
+int gxio_mpipe_adjust_timestamp_freq(gxio_mpipe_context_t *context,
                                     int32_t ppb);
 
-int gxio_mpipe_arm_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie);
+int gxio_mpipe_arm_pollfd(gxio_mpipe_context_t *context, int pollfd_cookie);
 
-int gxio_mpipe_close_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie);
+int gxio_mpipe_close_pollfd(gxio_mpipe_context_t *context, int pollfd_cookie);
 
-int gxio_mpipe_get_mmio_base(gxio_mpipe_context_t * context, HV_PTE *base);
+int gxio_mpipe_get_mmio_base(gxio_mpipe_context_t *context, HV_PTE *base);
 
-int gxio_mpipe_check_mmio_offset(gxio_mpipe_context_t * context,
+int gxio_mpipe_check_mmio_offset(gxio_mpipe_context_t *context,
                                 unsigned long offset, unsigned long size);
 
 #endif /* !__GXIO_MPIPE_LINUX_RPC_H__ */
index 476c5e5ca22cfe53714e699b667abf2995a192de..f0b04284468b804c424bf2b45e49cfdb3cb6972a 100644 (file)
 #define GXIO_MPIPE_INFO_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001)
 
 
-int gxio_mpipe_info_instance_aux(gxio_mpipe_info_context_t * context,
+int gxio_mpipe_info_instance_aux(gxio_mpipe_info_context_t *context,
                                 _gxio_mpipe_link_name_t name);
 
-int gxio_mpipe_info_enumerate_aux(gxio_mpipe_info_context_t * context,
+int gxio_mpipe_info_enumerate_aux(gxio_mpipe_info_context_t *context,
                                  unsigned int idx,
-                                 _gxio_mpipe_link_name_t * name,
-                                 _gxio_mpipe_link_mac_t * mac);
+                                 _gxio_mpipe_link_name_t *name,
+                                 _gxio_mpipe_link_mac_t *mac);
 
-int gxio_mpipe_info_get_mmio_base(gxio_mpipe_info_context_t * context,
+int gxio_mpipe_info_get_mmio_base(gxio_mpipe_info_context_t *context,
                                  HV_PTE *base);
 
-int gxio_mpipe_info_check_mmio_offset(gxio_mpipe_info_context_t * context,
+int gxio_mpipe_info_check_mmio_offset(gxio_mpipe_info_context_t *context,
                                      unsigned long offset, unsigned long size);
 
 #endif /* !__GXIO_MPIPE_INFO_LINUX_RPC_H__ */
index d95b96fd6c934d284f3b0669db7e960cc1c37b7a..376a4f771167ce9fec47c926da1938af2fd2ff88 100644 (file)
 #define GXIO_TRIO_OP_GET_MMIO_BASE     IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000)
 #define GXIO_TRIO_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001)
 
-int gxio_trio_alloc_asids(gxio_trio_context_t * context, unsigned int count,
+int gxio_trio_alloc_asids(gxio_trio_context_t *context, unsigned int count,
                          unsigned int first, unsigned int flags);
 
 
-int gxio_trio_alloc_memory_maps(gxio_trio_context_t * context,
+int gxio_trio_alloc_memory_maps(gxio_trio_context_t *context,
                                unsigned int count, unsigned int first,
                                unsigned int flags);
 
 
-int gxio_trio_alloc_scatter_queues(gxio_trio_context_t * context,
+int gxio_trio_alloc_scatter_queues(gxio_trio_context_t *context,
                                   unsigned int count, unsigned int first,
                                   unsigned int flags);
 
-int gxio_trio_alloc_pio_regions(gxio_trio_context_t * context,
+int gxio_trio_alloc_pio_regions(gxio_trio_context_t *context,
                                unsigned int count, unsigned int first,
                                unsigned int flags);
 
-int gxio_trio_init_pio_region_aux(gxio_trio_context_t * context,
+int gxio_trio_init_pio_region_aux(gxio_trio_context_t *context,
                                  unsigned int pio_region, unsigned int mac,
                                  uint32_t bus_address_hi, unsigned int flags);
 
 
-int gxio_trio_init_memory_map_mmu_aux(gxio_trio_context_t * context,
+int gxio_trio_init_memory_map_mmu_aux(gxio_trio_context_t *context,
                                      unsigned int map, unsigned long va,
                                      uint64_t size, unsigned int asid,
                                      unsigned int mac, uint64_t bus_address,
                                      unsigned int node,
                                      unsigned int order_mode);
 
-int gxio_trio_get_port_property(gxio_trio_context_t * context,
+int gxio_trio_get_port_property(gxio_trio_context_t *context,
                                struct pcie_trio_ports_property *trio_ports);
 
-int gxio_trio_config_legacy_intr(gxio_trio_context_t * context, int inter_x,
+int gxio_trio_config_legacy_intr(gxio_trio_context_t *context, int inter_x,
                                 int inter_y, int inter_ipi, int inter_event,
                                 unsigned int mac, unsigned int intx);
 
-int gxio_trio_config_msi_intr(gxio_trio_context_t * context, int inter_x,
+int gxio_trio_config_msi_intr(gxio_trio_context_t *context, int inter_x,
                              int inter_y, int inter_ipi, int inter_event,
                              unsigned int mac, unsigned int mem_map,
                              uint64_t mem_map_base, uint64_t mem_map_limit,
                              unsigned int asid);
 
 
-int gxio_trio_set_mps_mrs(gxio_trio_context_t * context, uint16_t mps,
+int gxio_trio_set_mps_mrs(gxio_trio_context_t *context, uint16_t mps,
                          uint16_t mrs, unsigned int mac);
 
-int gxio_trio_force_rc_link_up(gxio_trio_context_t * context, unsigned int mac);
+int gxio_trio_force_rc_link_up(gxio_trio_context_t *context, unsigned int mac);
 
-int gxio_trio_force_ep_link_up(gxio_trio_context_t * context, unsigned int mac);
+int gxio_trio_force_ep_link_up(gxio_trio_context_t *context, unsigned int mac);
 
-int gxio_trio_get_mmio_base(gxio_trio_context_t * context, HV_PTE *base);
+int gxio_trio_get_mmio_base(gxio_trio_context_t *context, HV_PTE *base);
 
-int gxio_trio_check_mmio_offset(gxio_trio_context_t * context,
+int gxio_trio_check_mmio_offset(gxio_trio_context_t *context,
                                unsigned long offset, unsigned long size);
 
 #endif /* !__GXIO_TRIO_LINUX_RPC_H__ */
index 8622e7d126adcec2c51af5366f86ff86a37ca0ae..79962a97de8e09a81d2e7ebcd7d8c5aecaed98f0 100644 (file)
 #define GXIO_USB_HOST_OP_GET_MMIO_BASE IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000)
 #define GXIO_USB_HOST_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001)
 
-int gxio_usb_host_cfg_interrupt(gxio_usb_host_context_t * context, int inter_x,
+int gxio_usb_host_cfg_interrupt(gxio_usb_host_context_t *context, int inter_x,
                                int inter_y, int inter_ipi, int inter_event);
 
-int gxio_usb_host_register_client_memory(gxio_usb_host_context_t * context,
+int gxio_usb_host_register_client_memory(gxio_usb_host_context_t *context,
                                         HV_PTE pte, unsigned int flags);
 
-int gxio_usb_host_get_mmio_base(gxio_usb_host_context_t * context,
+int gxio_usb_host_get_mmio_base(gxio_usb_host_context_t *context,
                                HV_PTE *base);
 
-int gxio_usb_host_check_mmio_offset(gxio_usb_host_context_t * context,
+int gxio_usb_host_check_mmio_offset(gxio_usb_host_context_t *context,
                                    unsigned long offset, unsigned long size);
 
 #endif /* !__GXIO_USB_HOST_LINUX_RPC_H__ */
index 5eedec0e988ef09392a4716329a25c1a760b06df..93c9636d2dd7879bf4867a17c65039ebd325eb93 100644 (file)
@@ -53,7 +53,7 @@ typedef struct {
  * @return Zero if the context was successfully initialized, else a
  *  GXIO_ERR_xxx error code.
  */
-extern int gxio_usb_host_init(gxio_usb_host_context_t * context, int usb_index,
+extern int gxio_usb_host_init(gxio_usb_host_context_t *context, int usb_index,
                              int is_ehci);
 
 /* Destroy a USB context.
@@ -68,20 +68,20 @@ extern int gxio_usb_host_init(gxio_usb_host_context_t * context, int usb_index,
  * @return Zero if the context was successfully destroyed, else a
  *  GXIO_ERR_xxx error code.
  */
-extern int gxio_usb_host_destroy(gxio_usb_host_context_t * context);
+extern int gxio_usb_host_destroy(gxio_usb_host_context_t *context);
 
 /* Retrieve the address of the shim's MMIO registers.
  *
  * @param context Pointer to a properly initialized gxio_usb_host_context_t.
  * @return The address of the shim's MMIO registers.
  */
-extern void *gxio_usb_host_get_reg_start(gxio_usb_host_context_t * context);
+extern void *gxio_usb_host_get_reg_start(gxio_usb_host_context_t *context);
 
 /* Retrieve the length of the shim's MMIO registers.
  *
  * @param context Pointer to a properly initialized gxio_usb_host_context_t.
  * @return The length of the shim's MMIO registers.
  */
-extern size_t gxio_usb_host_get_reg_len(gxio_usb_host_context_t * context);
+extern size_t gxio_usb_host_get_reg_len(gxio_usb_host_context_t *context);
 
 #endif /* _GXIO_USB_H_ */
index ed378416b86aa128b3eed7a3f20e010fedad740a..49120843ff96987feef36eff57365371fd07296b 100644 (file)
@@ -84,7 +84,7 @@ COMPAT_SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned int, offset_high,
 {
        return sys_llseek(fd, offset_high, offset_low, result, origin);
 }
+
 /* Provide the compat syscall number to call mapping. */
 #undef __SYSCALL
 #define __SYSCALL(nr, call) [nr] = (call),
diff --git a/arch/tile/kernel/futex_64.S b/arch/tile/kernel/futex_64.S
deleted file mode 100644 (file)
index f465d1e..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2011 Tilera Corporation. All Rights Reserved.
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License
- *   as published by the Free Software Foundation, version 2.
- *
- *   This program is distributed in the hope that it will be useful, but
- *   WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- *   NON INFRINGEMENT.  See the GNU General Public License for
- *   more details.
- *
- * Atomically access user memory, but use MMU to avoid propagating
- * kernel exceptions.
- */
-
-#include <linux/linkage.h>
-#include <asm/errno.h>
-#include <asm/futex.h>
-#include <asm/page.h>
-#include <asm/processor.h>
-
-/*
- * Provide a set of atomic memory operations supporting <asm/futex.h>.
- *
- * r0: user address to manipulate
- * r1: new value to write, or for cmpxchg, old value to compare against
- * r2: (cmpxchg only) new value to write
- *
- * Return __get_user struct, r0 with value, r1 with error.
- */
-#define FUTEX_OP(name, ...) \
-STD_ENTRY(futex_##name)                        \
-       __VA_ARGS__;                    \
-       {                               \
-        move   r1, zero;               \
-        jrp    lr                      \
-       };                              \
-       STD_ENDPROC(futex_##name);      \
-       .pushsection __ex_table,"a";    \
-       .quad 1b, get_user_fault;       \
-       .popsection
-
-       .pushsection .fixup,"ax"
-get_user_fault:
-       { movei r1, -EFAULT; jrp lr }
-       ENDPROC(get_user_fault)
-       .popsection
-
-FUTEX_OP(cmpxchg, mtspr CMPEXCH_VALUE, r1; 1: cmpexch4 r0, r0, r2)
-FUTEX_OP(set, 1: exch4 r0, r0, r1)
-FUTEX_OP(add, 1: fetchadd4 r0, r0, r1)
-FUTEX_OP(or, 1: fetchor4 r0, r0, r1)
-FUTEX_OP(andn, nor r1, r1, zero; 1: fetchand4 r0, r0, r1)
index 4c34caea9dd31041bdf263a5c72ec3a3ba46f19c..74c91729a62a9290e12bb31ea96ab7ad240aebc2 100644 (file)
@@ -1268,8 +1268,7 @@ static void __init validate_va(void)
        if ((long)VMALLOC_START >= 0)
                early_panic(
                        "Linux VMALLOC region below the 2GB line (%#lx)!\n"
-                       "Reconfigure the kernel with fewer NR_HUGE_VMAPS\n"
-                       "or smaller VMALLOC_RESERVE.\n",
+                       "Reconfigure the kernel with smaller VMALLOC_RESERVE.\n",
                        VMALLOC_START);
 #endif
 }
index b425fb6a480d3e40c6d7fd2fab4bed1a41c7dbc0..b030b4e78845b596c1fc429687e360a2791e7046 100644 (file)
@@ -551,8 +551,8 @@ static tilegx_bundle_bits  jit_x1_bnezt(int ra, int broff)
 /*
  * This function generates unalign fixup JIT.
  *
- * We fist find unalign load/store instruction's destination, source
- * reguisters: ra, rb and rd. and 3 scratch registers by calling
+ * We first find unalign load/store instruction's destination, source
+ * registers: ra, rb and rd. and 3 scratch registers by calling
  * find_regs(...). 3 scratch clobbers should not alias with any register
  * used in the fault bundle. Then analyze the fault bundle to determine
  * if it's a load or store, operand width, branch or address increment etc.
index 4c288f199453a41792f450ead64f71425218d0f4..6c0571216a9d67f81a09ff331a601d22ae881566 100644 (file)
@@ -149,8 +149,6 @@ static inline int vmalloc_fault(pgd_t *pgd, unsigned long address)
        pmd_k = vmalloc_sync_one(pgd, address);
        if (!pmd_k)
                return -1;
-       if (pmd_huge(*pmd_k))
-               return 0;   /* support TILE huge_vmap() API */
        pte_k = pte_offset_kernel(pmd_k, address);
        if (!pte_present(*pte_k))
                return -1;
index 4e316deb92fd58f084e57d01a42104e65c68c29b..0fa1acfac79ad2a25ba82aed6607e36f868ade7c 100644 (file)
@@ -827,10 +827,6 @@ void __init mem_init(void)
               FIXADDR_START, FIXADDR_TOP + PAGE_SIZE - 1);
        printk(KERN_DEBUG "  PKMAP   %#lx - %#lx\n",
               PKMAP_BASE, PKMAP_ADDR(LAST_PKMAP) - 1);
-#endif
-#ifdef CONFIG_HUGEVMAP
-       printk(KERN_DEBUG "  HUGEMAP %#lx - %#lx\n",
-              HUGE_VMAP_BASE, HUGE_VMAP_END - 1);
 #endif
        printk(KERN_DEBUG "  VMALLOC %#lx - %#lx\n",
               _VMALLOC_START, _VMALLOC_END - 1);
index 2deaddf3e01f2329c2aded0d083c65e005a115f2..4fd9ec0b58edcb57d0b3346d41eea54c6f66c35f 100644 (file)
@@ -127,8 +127,7 @@ void shatter_huge_page(unsigned long addr)
        }
 
        /* Shatter the huge page into the preallocated L2 page table. */
-       pmd_populate_kernel(&init_mm, pmd,
-                           get_prealloc_pte(pte_pfn(*(pte_t *)pmd)));
+       pmd_populate_kernel(&init_mm, pmd, get_prealloc_pte(pmd_pfn(*pmd)));
 
 #ifdef __PAGETABLE_PMD_FOLDED
        /* Walk every pgd on the system and update the pmd there. */
index e241a1930c9898003ed8f6097f2bb47208c8b4cd..ee2fb9d37745887eb16255cbd30adacbdcc1ecae 100644 (file)
@@ -481,11 +481,12 @@ config X86_INTEL_LPSS
        bool "Intel Low Power Subsystem Support"
        depends on ACPI
        select COMMON_CLK
+       select PINCTRL
        ---help---
          Select to build support for Intel Low Power Subsystem such as
          found on Intel Lynxpoint PCH. Selecting this option enables
-         things like clock tree (common clock framework) which are needed
-         by the LPSS peripheral drivers.
+         things like clock tree (common clock framework) and pincontrol
+         which are needed by the LPSS peripheral drivers.
 
 config X86_RDC321X
        bool "RDC R-321x SoC"
index 6aef9fbc09b7a48ec82c13e04b1f8c761dc34661..b913915e8e631f9c9ec2996fde3862bd33e2edce 100644 (file)
@@ -79,30 +79,38 @@ static inline int phys_to_machine_mapping_valid(unsigned long pfn)
        return get_phys_to_machine(pfn) != INVALID_P2M_ENTRY;
 }
 
-static inline unsigned long mfn_to_pfn(unsigned long mfn)
+static inline unsigned long mfn_to_pfn_no_overrides(unsigned long mfn)
 {
        unsigned long pfn;
-       int ret = 0;
+       int ret;
 
        if (xen_feature(XENFEAT_auto_translated_physmap))
                return mfn;
 
-       if (unlikely(mfn >= machine_to_phys_nr)) {
-               pfn = ~0;
-               goto try_override;
-       }
-       pfn = 0;
+       if (unlikely(mfn >= machine_to_phys_nr))
+               return ~0;
+
        /*
         * The array access can fail (e.g., device space beyond end of RAM).
         * In such cases it doesn't matter what we return (we return garbage),
         * but we must handle the fault without crashing!
         */
        ret = __get_user(pfn, &machine_to_phys_mapping[mfn]);
-try_override:
-       /* ret might be < 0 if there are no entries in the m2p for mfn */
        if (ret < 0)
-               pfn = ~0;
-       else if (get_phys_to_machine(pfn) != mfn)
+               return ~0;
+
+       return pfn;
+}
+
+static inline unsigned long mfn_to_pfn(unsigned long mfn)
+{
+       unsigned long pfn;
+
+       if (xen_feature(XENFEAT_auto_translated_physmap))
+               return mfn;
+
+       pfn = mfn_to_pfn_no_overrides(mfn);
+       if (get_phys_to_machine(pfn) != mfn) {
                /*
                 * If this appears to be a foreign mfn (because the pfn
                 * doesn't map back to the mfn), then check the local override
@@ -111,6 +119,7 @@ try_override:
                 * m2p_find_override_pfn returns ~0 if it doesn't find anything.
                 */
                pfn = m2p_find_override_pfn(mfn, ~0);
+       }
 
        /* 
         * pfn is ~0 if there are no entries in the m2p for mfn or if the
index 8355c84b9729df767945c5f4c8a5f7c5db15fab8..897783b3302a9cd0d0af3efad49c94e45f9f7e9e 100644 (file)
@@ -1506,7 +1506,7 @@ static int __init init_hw_perf_events(void)
                err = amd_pmu_init();
                break;
        default:
-               return 0;
+               err = -ENOTSUPP;
        }
        if (err != 0) {
                pr_cont("no PMU driver, software events only.\n");
@@ -1883,9 +1883,9 @@ static struct pmu pmu = {
 
 void arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now)
 {
-       userpg->cap_usr_time = 0;
-       userpg->cap_usr_time_zero = 0;
-       userpg->cap_usr_rdpmc = x86_pmu.attr_rdpmc;
+       userpg->cap_user_time = 0;
+       userpg->cap_user_time_zero = 0;
+       userpg->cap_user_rdpmc = x86_pmu.attr_rdpmc;
        userpg->pmc_width = x86_pmu.cntval_bits;
 
        if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
@@ -1894,13 +1894,13 @@ void arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now)
        if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
                return;
 
-       userpg->cap_usr_time = 1;
+       userpg->cap_user_time = 1;
        userpg->time_mult = this_cpu_read(cyc2ns);
        userpg->time_shift = CYC2NS_SCALE_FACTOR;
        userpg->time_offset = this_cpu_read(cyc2ns_offset) - now;
 
        if (sched_clock_stable && !check_tsc_disabled()) {
-               userpg->cap_usr_time_zero = 1;
+               userpg->cap_user_time_zero = 1;
                userpg->time_zero = this_cpu_read(cyc2ns_offset);
        }
 }
index c62d88396ad52161a4ac1608f196322913535ff0..f31a1655d1ff5bd602239e211b14bdd28d95a79a 100644 (file)
@@ -899,8 +899,8 @@ static __initconst const u64 atom_hw_cache_event_ids
 static struct extra_reg intel_slm_extra_regs[] __read_mostly =
 {
        /* must define OFFCORE_RSP_X first, see intel_fixup_er() */
-       INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x768005ffff, RSP_0),
-       INTEL_UEVENT_EXTRA_REG(0x02b7, MSR_OFFCORE_RSP_1, 0x768005ffff, RSP_1),
+       INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x768005ffffull, RSP_0),
+       INTEL_UEVENT_EXTRA_REG(0x02b7, MSR_OFFCORE_RSP_1, 0x768005ffffull, RSP_1),
        EVENT_EXTRA_END
 };
 
@@ -2325,6 +2325,7 @@ __init int intel_pmu_init(void)
                break;
 
        case 55: /* Atom 22nm "Silvermont" */
+       case 77: /* Avoton "Silvermont" */
                memcpy(hw_cache_event_ids, slm_hw_cache_event_ids,
                        sizeof(hw_cache_event_ids));
                memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs,
index 63438aad177fc0c8e664066f80cf46f3493acfbe..ab3ba1c1b7dd2c425dd5edf4c2b5091d76355b34 100644 (file)
@@ -584,6 +584,7 @@ struct event_constraint intel_snb_pebs_event_constraints[] = {
        INTEL_EVENT_CONSTRAINT(0xd0, 0xf),    /* MEM_UOP_RETIRED.* */
        INTEL_EVENT_CONSTRAINT(0xd1, 0xf),    /* MEM_LOAD_UOPS_RETIRED.* */
        INTEL_EVENT_CONSTRAINT(0xd2, 0xf),    /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
+       INTEL_EVENT_CONSTRAINT(0xd3, 0xf),    /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
        INTEL_UEVENT_CONSTRAINT(0x02d4, 0xf), /* MEM_LOAD_UOPS_MISC_RETIRED.LLC_MISS */
        EVENT_CONSTRAINT_END
 };
index 8ed44589b0e486eda5a45efa74f3f4d3836a730f..4118f9f683151e99402740f1882b205a261a1465 100644 (file)
@@ -2706,14 +2706,14 @@ static void uncore_pmu_init_hrtimer(struct intel_uncore_box *box)
        box->hrtimer.function = uncore_pmu_hrtimer;
 }
 
-struct intel_uncore_box *uncore_alloc_box(struct intel_uncore_type *type, int cpu)
+static struct intel_uncore_box *uncore_alloc_box(struct intel_uncore_type *type, int node)
 {
        struct intel_uncore_box *box;
        int i, size;
 
        size = sizeof(*box) + type->num_shared_regs * sizeof(struct intel_uncore_extra_reg);
 
-       box = kzalloc_node(size, GFP_KERNEL, cpu_to_node(cpu));
+       box = kzalloc_node(size, GFP_KERNEL, node);
        if (!box)
                return NULL;
 
@@ -3031,7 +3031,7 @@ static int uncore_validate_group(struct intel_uncore_pmu *pmu,
        struct intel_uncore_box *fake_box;
        int ret = -EINVAL, n;
 
-       fake_box = uncore_alloc_box(pmu->type, smp_processor_id());
+       fake_box = uncore_alloc_box(pmu->type, NUMA_NO_NODE);
        if (!fake_box)
                return -ENOMEM;
 
@@ -3294,7 +3294,7 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id
        }
 
        type = pci_uncores[UNCORE_PCI_DEV_TYPE(id->driver_data)];
-       box = uncore_alloc_box(type, 0);
+       box = uncore_alloc_box(type, NUMA_NO_NODE);
        if (!box)
                return -ENOMEM;
 
@@ -3499,7 +3499,7 @@ static int uncore_cpu_prepare(int cpu, int phys_id)
                        if (pmu->func_id < 0)
                                pmu->func_id = j;
 
-                       box = uncore_alloc_box(type, cpu);
+                       box = uncore_alloc_box(type, cpu_to_node(cpu));
                        if (!box)
                                return -ENOMEM;
 
index 1b69951a81e2b61bff752621872d5750736f96d4..b077f4cc225a29764e89389e099fbd0ae2006707 100644 (file)
@@ -487,21 +487,6 @@ ENDPROC(native_usergs_sysret64)
        TRACE_IRQS_OFF
        .endm
 
-ENTRY(save_rest)
-       PARTIAL_FRAME 1 (REST_SKIP+8)
-       movq 5*8+16(%rsp), %r11 /* save return address */
-       movq_cfi rbx, RBX+16
-       movq_cfi rbp, RBP+16
-       movq_cfi r12, R12+16
-       movq_cfi r13, R13+16
-       movq_cfi r14, R14+16
-       movq_cfi r15, R15+16
-       movq %r11, 8(%rsp)      /* return address */
-       FIXUP_TOP_OF_STACK %r11, 16
-       ret
-       CFI_ENDPROC
-END(save_rest)
-
 /* save complete stack frame */
        .pushsection .kprobes.text, "ax"
 ENTRY(save_paranoid)
index 7123b5df479d872def8ff437fcd407c5c4d5ca50..af99f71aeb7f159a6ba7f1da0596ae2843d67e47 100644 (file)
@@ -216,6 +216,7 @@ int apply_microcode_amd(int cpu)
        /* need to apply patch? */
        if (rev >= mc_amd->hdr.patch_id) {
                c->microcode = rev;
+               uci->cpu_sig.rev = rev;
                return 0;
        }
 
index 563ed91e6faa3a2adac62ddeb8caff7e5ad50f24..e643e744e4d8bf855ce1889bdae58b51001aab45 100644 (file)
@@ -352,12 +352,28 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
        },
        {       /* Handle problems with rebooting on the Precision M6600. */
                .callback = set_pci_reboot,
-               .ident = "Dell OptiPlex 990",
+               .ident = "Dell Precision M6600",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Precision M6600"),
                },
        },
+       {       /* Handle problems with rebooting on the Dell PowerEdge C6100. */
+               .callback = set_pci_reboot,
+               .ident = "Dell PowerEdge C6100",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "C6100"),
+               },
+       },
+       {       /* Some C6100 machines were shipped with vendor being 'Dell'. */
+               .callback = set_pci_reboot,
+               .ident = "Dell PowerEdge C6100",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "C6100"),
+               },
+       },
        { }
 };
 
index aecc98a93d1b42f39261fcc9102be5515185d78a..6cacab671f9b76a35aaf49d41431b12e788e5bbe 100644 (file)
@@ -653,6 +653,7 @@ static void announce_cpu(int cpu, int apicid)
 {
        static int current_node = -1;
        int node = early_cpu_to_node(cpu);
+       int max_cpu_present = find_last_bit(cpumask_bits(cpu_present_mask), NR_CPUS);
 
        if (system_state == SYSTEM_BOOTING) {
                if (node != current_node) {
@@ -661,7 +662,7 @@ static void announce_cpu(int cpu, int apicid)
                        current_node = node;
                        pr_info("Booting Node %3d, Processors ", node);
                }
-               pr_cont(" #%d%s", cpu, cpu == (nr_cpu_ids - 1) ? " OK\n" : "");
+               pr_cont(" #%4d%s", cpu, cpu == max_cpu_present ? " OK\n" : "");
                return;
        } else
                pr_info("Booting Node %d Processor %d APIC 0x%x\n",
index 22513e96b0125c54510722afab5f7abab8f73405..86179d4098938d50e13f25b6e75cfe8a198b7b80 100644 (file)
@@ -72,14 +72,14 @@ __init int create_simplefb(const struct screen_info *si,
         * the part that is occupied by the framebuffer */
        len = mode->height * mode->stride;
        len = PAGE_ALIGN(len);
-       if (len > si->lfb_size << 16) {
+       if (len > (u64)si->lfb_size << 16) {
                printk(KERN_WARNING "sysfb: VRAM smaller than advertised\n");
                return -EINVAL;
        }
 
        /* setup IORESOURCE_MEM as framebuffer memory */
        memset(&res, 0, sizeof(res));
-       res.flags = IORESOURCE_MEM;
+       res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
        res.name = simplefb_resname;
        res.start = si->lfb_base;
        res.end = si->lfb_base + len - 1;
index 2bc1e81045b0f20f90ad2500c3acae318de1e8ee..ddc3f3d2afdb155b3ce39f4049c800356fb42d04 100644 (file)
@@ -2025,6 +2025,17 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt)
        return rc;
 }
 
+static int em_ret_far_imm(struct x86_emulate_ctxt *ctxt)
+{
+        int rc;
+
+        rc = em_ret_far(ctxt);
+        if (rc != X86EMUL_CONTINUE)
+                return rc;
+        rsp_increment(ctxt, ctxt->src.val);
+        return X86EMUL_CONTINUE;
+}
+
 static int em_cmpxchg(struct x86_emulate_ctxt *ctxt)
 {
        /* Save real source value, then compare EAX against destination. */
@@ -3763,7 +3774,8 @@ static const struct opcode opcode_table[256] = {
        G(ByteOp, group11), G(0, group11),
        /* 0xC8 - 0xCF */
        I(Stack | SrcImmU16 | Src2ImmByte, em_enter), I(Stack, em_leave),
-       N, I(ImplicitOps | Stack, em_ret_far),
+       I(ImplicitOps | Stack | SrcImmU16, em_ret_far_imm),
+       I(ImplicitOps | Stack, em_ret_far),
        D(ImplicitOps), DI(SrcImmByte, intn),
        D(ImplicitOps | No64), II(ImplicitOps, em_iret, iret),
        /* 0xD0 - 0xD7 */
index 04333015917984a6b65f3fd0ab4ecbad2f5b1f2a..ad75d77999d085037469539d42a5df140533971d 100644 (file)
@@ -99,6 +99,7 @@ struct guest_walker {
        pt_element_t prefetch_ptes[PTE_PREFETCH_NUM];
        gpa_t pte_gpa[PT_MAX_FULL_LEVELS];
        pt_element_t __user *ptep_user[PT_MAX_FULL_LEVELS];
+       bool pte_writable[PT_MAX_FULL_LEVELS];
        unsigned pt_access;
        unsigned pte_access;
        gfn_t gfn;
@@ -235,6 +236,22 @@ static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,
                if (pte == orig_pte)
                        continue;
 
+               /*
+                * If the slot is read-only, simply do not process the accessed
+                * and dirty bits.  This is the correct thing to do if the slot
+                * is ROM, and page tables in read-as-ROM/write-as-MMIO slots
+                * are only supported if the accessed and dirty bits are already
+                * set in the ROM (so that MMIO writes are never needed).
+                *
+                * Note that NPT does not allow this at all and faults, since
+                * it always wants nested page table entries for the guest
+                * page tables to be writable.  And EPT works but will simply
+                * overwrite the read-only memory to set the accessed and dirty
+                * bits.
+                */
+               if (unlikely(!walker->pte_writable[level - 1]))
+                       continue;
+
                ret = FNAME(cmpxchg_gpte)(vcpu, mmu, ptep_user, index, orig_pte, pte);
                if (ret)
                        return ret;
@@ -309,7 +326,8 @@ retry_walk:
                        goto error;
                real_gfn = gpa_to_gfn(real_gfn);
 
-               host_addr = gfn_to_hva(vcpu->kvm, real_gfn);
+               host_addr = gfn_to_hva_prot(vcpu->kvm, real_gfn,
+                                           &walker->pte_writable[walker->level - 1]);
                if (unlikely(kvm_is_error_hva(host_addr)))
                        goto error;
 
index 1f1da43ff2a2ca66a137c434cf738dbf7a03e704..3b8e7459dd4db84a4c6f72816cd2c0629d866ee4 100644 (file)
@@ -5339,6 +5339,17 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu)
                return 0;
        }
 
+       /*
+        * EPT violation happened while executing iret from NMI,
+        * "blocked by NMI" bit has to be set before next VM entry.
+        * There are errata that may cause this bit to not be set:
+        * AAK134, BY25.
+        */
+       if (!(to_vmx(vcpu)->idt_vectoring_info & VECTORING_INFO_VALID_MASK) &&
+                       cpu_has_virtual_nmis() &&
+                       (exit_qualification & INTR_INFO_UNBLOCK_NMI))
+               vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO, GUEST_INTR_STATE_NMI);
+
        gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
        trace_kvm_page_fault(gpa, exit_qualification);
 
@@ -7766,6 +7777,10 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
                vmcs_write64(GUEST_PDPTR1, vmcs12->guest_pdptr1);
                vmcs_write64(GUEST_PDPTR2, vmcs12->guest_pdptr2);
                vmcs_write64(GUEST_PDPTR3, vmcs12->guest_pdptr3);
+               __clear_bit(VCPU_EXREG_PDPTR,
+                               (unsigned long *)&vcpu->arch.regs_avail);
+               __clear_bit(VCPU_EXREG_PDPTR,
+                               (unsigned long *)&vcpu->arch.regs_dirty);
        }
 
        kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs12->guest_rsp);
index 5596c7bdd327b1af38138a3d32be36be3e21cb17..082e88129712b4eb9e2027852c890a02ff31a1c7 100644 (file)
@@ -700,7 +700,7 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end,
        if (!(pci_probe & PCI_PROBE_MMCONF) || pci_mmcfg_arch_init_failed)
                return -ENODEV;
 
-       if (start > end || !addr)
+       if (start > end)
                return -EINVAL;
 
        mutex_lock(&pci_mmcfg_lock);
@@ -716,6 +716,11 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end,
                return -EEXIST;
        }
 
+       if (!addr) {
+               mutex_unlock(&pci_mmcfg_lock);
+               return -EINVAL;
+       }
+
        rc = -EBUSY;
        cfg = pci_mmconfig_alloc(seg, start, end, addr);
        if (cfg == NULL) {
index 90f6ed127096566ab06c0a9e6f25a355ccdfc048..c7e22ab29a5a2eb6ce3dd75f0fd3e0b26be2d61b 100644 (file)
@@ -912,10 +912,13 @@ void __init efi_enter_virtual_mode(void)
 
        for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
                md = p;
-               if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
-                   md->type != EFI_BOOT_SERVICES_CODE &&
-                   md->type != EFI_BOOT_SERVICES_DATA)
-                       continue;
+               if (!(md->attribute & EFI_MEMORY_RUNTIME)) {
+#ifdef CONFIG_X86_64
+                       if (md->type != EFI_BOOT_SERVICES_CODE &&
+                           md->type != EFI_BOOT_SERVICES_DATA)
+#endif
+                               continue;
+               }
 
                size = md->num_pages << EFI_PAGE_SHIFT;
                end = md->phys_addr + size;
index 8b901e8d782dadf00091ac88a6fc859c54c4d1de..a61c7d5811beac47e2549cd6fd44118bc5bf7b28 100644 (file)
@@ -879,7 +879,6 @@ int m2p_add_override(unsigned long mfn, struct page *page,
        unsigned long uninitialized_var(address);
        unsigned level;
        pte_t *ptep = NULL;
-       int ret = 0;
 
        pfn = page_to_pfn(page);
        if (!PageHighMem(page)) {
@@ -926,8 +925,8 @@ int m2p_add_override(unsigned long mfn, struct page *page,
         * frontend pages while they are being shared with the backend,
         * because mfn_to_pfn (that ends up being called by GUPF) will
         * return the backend pfn rather than the frontend pfn. */
-       ret = __get_user(pfn, &machine_to_phys_mapping[mfn]);
-       if (ret == 0 && get_phys_to_machine(pfn) == mfn)
+       pfn = mfn_to_pfn_no_overrides(mfn);
+       if (get_phys_to_machine(pfn) == mfn)
                set_phys_to_machine(pfn, FOREIGN_FRAME(mfn));
 
        return 0;
@@ -942,7 +941,6 @@ int m2p_remove_override(struct page *page,
        unsigned long uninitialized_var(address);
        unsigned level;
        pte_t *ptep = NULL;
-       int ret = 0;
 
        pfn = page_to_pfn(page);
        mfn = get_phys_to_machine(pfn);
@@ -1029,8 +1027,8 @@ int m2p_remove_override(struct page *page,
         * the original pfn causes mfn_to_pfn(mfn) to return the frontend
         * pfn again. */
        mfn &= ~FOREIGN_FRAME_BIT;
-       ret = __get_user(pfn, &machine_to_phys_mapping[mfn]);
-       if (ret == 0 && get_phys_to_machine(pfn) == FOREIGN_FRAME(mfn) &&
+       pfn = mfn_to_pfn_no_overrides(mfn);
+       if (get_phys_to_machine(pfn) == FOREIGN_FRAME(mfn) &&
                        m2p_find_override(mfn) == NULL)
                set_phys_to_machine(pfn, mfn);
 
index 253f63fceea104978c6e5d1f54ba81e1e3581b20..be6b8607895748304c860c61603d24a29bacfa34 100644 (file)
@@ -259,6 +259,14 @@ void xen_uninit_lock_cpu(int cpu)
 }
 
 
+/*
+ * Our init of PV spinlocks is split in two init functions due to us
+ * using paravirt patching and jump labels patching and having to do
+ * all of this before SMP code is invoked.
+ *
+ * The paravirt patching needs to be done _before_ the alternative asm code
+ * is started, otherwise we would not patch the core kernel code.
+ */
 void __init xen_init_spinlocks(void)
 {
 
@@ -267,12 +275,26 @@ void __init xen_init_spinlocks(void)
                return;
        }
 
-       static_key_slow_inc(&paravirt_ticketlocks_enabled);
-
        pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(xen_lock_spinning);
        pv_lock_ops.unlock_kick = xen_unlock_kick;
 }
 
+/*
+ * While the jump_label init code needs to happend _after_ the jump labels are
+ * enabled and before SMP is started. Hence we use pre-SMP initcall level
+ * init. We cannot do it in xen_init_spinlocks as that is done before
+ * jump labels are activated.
+ */
+static __init int xen_init_spinlocks_jump(void)
+{
+       if (!xen_pvspin)
+               return 0;
+
+       static_key_slow_inc(&paravirt_ticketlocks_enabled);
+       return 0;
+}
+early_initcall(xen_init_spinlocks_jump);
+
 static __init int xen_parse_nopvspin(char *arg)
 {
        xen_pvspin = false;
index 7f38e40fee0819a74ec6b3d10c759c07d3b04bb4..2429515c05c2ed1b6f457a60def817c33c178651 100644 (file)
@@ -99,11 +99,16 @@ config BLK_DEV_THROTTLING
 
        See Documentation/cgroups/blkio-controller.txt for more information.
 
-config CMDLINE_PARSER
+config BLK_CMDLINE_PARSER
        bool "Block device command line partition parser"
        default n
        ---help---
-       Parsing command line, get the partitions information.
+       Enabling this option allows you to specify the partition layout from
+       the kernel boot args.  This is typically of use for embedded devices
+       which don't otherwise have any standardized method for listing the
+       partitions on a block device.
+
+       See Documentation/block/cmdline-partition.txt for more information.
 
 menu "Partition Types"
 
index 4fa4be544ece94c05d0956a0c6f488c1f7a65161..671a83d063a5ba290c93efc08457eba6217ea80d 100644 (file)
@@ -18,4 +18,4 @@ obj-$(CONFIG_IOSCHED_CFQ)     += cfq-iosched.o
 
 obj-$(CONFIG_BLOCK_COMPAT)     += compat_ioctl.o
 obj-$(CONFIG_BLK_DEV_INTEGRITY)        += blk-integrity.o
-obj-$(CONFIG_CMDLINE_PARSER)   += cmdline-parser.o
+obj-$(CONFIG_BLK_CMDLINE_PARSER)       += cmdline-parser.o
index e90c7c164c83b8dc58f36393bb5748c0110e6184..4e491d9b529255476939b8608d91718c40140059 100644 (file)
@@ -235,8 +235,13 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg,
        blkg->online = true;
        spin_unlock(&blkcg->lock);
 
-       if (!ret)
+       if (!ret) {
+               if (blkcg == &blkcg_root) {
+                       q->root_blkg = blkg;
+                       q->root_rl.blkg = blkg;
+               }
                return blkg;
+       }
 
        /* @blkg failed fully initialized, use the usual release path */
        blkg_put(blkg);
@@ -334,6 +339,15 @@ static void blkg_destroy(struct blkcg_gq *blkg)
        if (rcu_dereference_raw(blkcg->blkg_hint) == blkg)
                rcu_assign_pointer(blkcg->blkg_hint, NULL);
 
+       /*
+        * If root blkg is destroyed.  Just clear the pointer since root_rl
+        * does not take reference on root blkg.
+        */
+       if (blkcg == &blkcg_root) {
+               blkg->q->root_blkg = NULL;
+               blkg->q->root_rl.blkg = NULL;
+       }
+
        /*
         * Put the reference taken at the time of creation so that when all
         * queues are gone, group can be destroyed.
@@ -360,13 +374,6 @@ static void blkg_destroy_all(struct request_queue *q)
                blkg_destroy(blkg);
                spin_unlock(&blkcg->lock);
        }
-
-       /*
-        * root blkg is destroyed.  Just clear the pointer since
-        * root_rl does not take reference on root blkg.
-        */
-       q->root_blkg = NULL;
-       q->root_rl.blkg = NULL;
 }
 
 /*
@@ -970,8 +977,6 @@ int blkcg_activate_policy(struct request_queue *q,
                ret = PTR_ERR(blkg);
                goto out_unlock;
        }
-       q->root_blkg = blkg;
-       q->root_rl.blkg = blkg;
 
        list_for_each_entry(blkg, &q->blkg_list, q_node)
                cnt++;
index c04505358342e132a0a3164cd154d12d52a7ad98..0a00e4ecf87cae37a3d310c8dfd32869ac24c161 100644 (file)
@@ -1549,11 +1549,9 @@ get_rq:
        if (plug) {
                /*
                 * If this is the first request added after a plug, fire
-                * of a plug trace. If others have been added before, check
-                * if we have multiple devices in this plug. If so, make a
-                * note to sort the list before dispatch.
+                * of a plug trace.
                 */
-               if (list_empty(&plug->list))
+               if (!request_count)
                        trace_block_plug(q);
                else {
                        if (request_count >= BLK_MAX_REQUEST_COUNT) {
index e7062139612914b95917405fc3da52e4498f066d..ae4f27d7944e9a662ddbb51464bd18e10f4707a4 100644 (file)
@@ -68,9 +68,9 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
        spin_lock_irq(q->queue_lock);
 
        if (unlikely(blk_queue_dying(q))) {
+               rq->cmd_flags |= REQ_QUIET; 
                rq->errors = -ENXIO;
-               if (rq->end_io)
-                       rq->end_io(rq, rq->errors);
+               __blk_end_request_all(rq, rq->errors);
                spin_unlock_irq(q->queue_lock);
                return;
        }
index c50ecf0ea3b17c652db8c134905de38e56713851..026c1517505f2aaab4780a15735850104abbf7eb 100644 (file)
@@ -195,17 +195,17 @@ EXPORT_SYMBOL(blk_queue_make_request);
 /**
  * blk_queue_bounce_limit - set bounce buffer limit for queue
  * @q: the request queue for the device
- * @dma_mask: the maximum address the device can handle
+ * @max_addr: the maximum address the device can handle
  *
  * Description:
  *    Different hardware can have different requirements as to what pages
  *    it can do I/O directly to. A low level driver can call
  *    blk_queue_bounce_limit to have lower memory pages allocated as bounce
- *    buffers for doing I/O to pages residing above @dma_mask.
+ *    buffers for doing I/O to pages residing above @max_addr.
  **/
-void blk_queue_bounce_limit(struct request_queue *q, u64 dma_mask)
+void blk_queue_bounce_limit(struct request_queue *q, u64 max_addr)
 {
-       unsigned long b_pfn = dma_mask >> PAGE_SHIFT;
+       unsigned long b_pfn = max_addr >> PAGE_SHIFT;
        int dma = 0;
 
        q->bounce_gfp = GFP_NOIO;
index dabb9d02cf9a509655f67ae169ac0c3a706d8f8e..434944cbd761884f0f6d9ffdfe96adc00afd1e5c 100644 (file)
@@ -1803,7 +1803,7 @@ static u64 cfqg_prfill_avg_queue_size(struct seq_file *sf,
 
        if (samples) {
                v = blkg_stat_read(&cfqg->stats.avg_queue_size_sum);
-               do_div(v, samples);
+               v = div64_u64(v, samples);
        }
        __blkg_prfill_u64(sf, pd, v);
        return 0;
@@ -4358,7 +4358,7 @@ static int cfq_init_queue(struct request_queue *q, struct elevator_type *e)
        if (!eq)
                return -ENOMEM;
 
-       cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node);
+       cfqd = kzalloc_node(sizeof(*cfqd), GFP_KERNEL, q->node);
        if (!cfqd) {
                kobject_put(&eq->kobj);
                return -ENOMEM;
index 20614a33236220d0e79d99a2cfaf99822327bc57..9ef66406c625412b79296d6e4f9186611b95b6f6 100644 (file)
@@ -346,7 +346,7 @@ static int deadline_init_queue(struct request_queue *q, struct elevator_type *e)
        if (!eq)
                return -ENOMEM;
 
-       dd = kmalloc_node(sizeof(*dd), GFP_KERNEL | __GFP_ZERO, q->node);
+       dd = kzalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
        if (!dd) {
                kobject_put(&eq->kobj);
                return -ENOMEM;
index 668394d185885bc3fcc878697878a4cb07be899e..2bcbd8cc14d4b23780a3cfc262857a87f7c5d67e 100644 (file)
@@ -155,7 +155,7 @@ struct elevator_queue *elevator_alloc(struct request_queue *q,
 {
        struct elevator_queue *eq;
 
-       eq = kmalloc_node(sizeof(*eq), GFP_KERNEL | __GFP_ZERO, q->node);
+       eq = kzalloc_node(sizeof(*eq), GFP_KERNEL, q->node);
        if (unlikely(!eq))
                goto err;
 
index dadf42b454a383299231fa46abee1631aab53196..791f419431322882a915f88995df7b72552d5507 100644 (file)
@@ -1252,8 +1252,7 @@ struct gendisk *alloc_disk_node(int minors, int node_id)
 {
        struct gendisk *disk;
 
-       disk = kmalloc_node(sizeof(struct gendisk),
-                               GFP_KERNEL | __GFP_ZERO, node_id);
+       disk = kzalloc_node(sizeof(struct gendisk), GFP_KERNEL, node_id);
        if (disk) {
                if (!init_part_stats(&disk->part0)) {
                        kfree(disk);
index 87a32086535d5228b513af3935d29765b763b2ec..9b29a996c3114a3d09c41abdcaaa0f3f19abe3ff 100644 (file)
@@ -263,7 +263,7 @@ config SYSV68_PARTITION
 
 config CMDLINE_PARTITION
        bool "Command line partition support" if PARTITION_ADVANCED
-       select CMDLINE_PARSER
+       select BLK_CMDLINE_PARSER
        help
-         Say Y here if you would read the partitions table from bootargs.
+         Say Y here if you want to read the partition table from bootargs.
          The format for the command line is just like mtdparts.
index 56cf4ffad51ed903128ac079d9845acafbd639a4..5141b563adf1b9a41c6b6054a8d2dcf5618da4d6 100644 (file)
@@ -2,15 +2,15 @@
  * Copyright (C) 2013 HUAWEI
  * Author: Cai Zhiyong <caizhiyong@huawei.com>
  *
- * Read block device partition table from command line.
- * The partition used for fixed block device (eMMC) embedded device.
- * It is no MBR, save storage space. Bootloader can be easily accessed
+ * Read block device partition table from the command line.
+ * Typically used for fixed block (eMMC) embedded devices.
+ * It has no MBR, so saves storage space. Bootloader can be easily accessed
  * by absolute address of data on the block device.
  * Users can easily change the partition.
  *
  * The format for the command line is just like mtdparts.
  *
- * Verbose config please reference "Documentation/block/cmdline-partition.txt"
+ * For further information, see "Documentation/block/cmdline-partition.txt"
  *
  */
 
index 69ce573f1224560b4f5c7532e21053b27c651da4..71f337aefa3905feaca892b7ac3b49b4bcb411e3 100644 (file)
@@ -776,6 +776,22 @@ config CRYPTO_AES_ARM
 
          See <http://csrc.nist.gov/encryption/aes/> for more information.
 
+config CRYPTO_AES_ARM_BS
+       tristate "Bit sliced AES using NEON instructions"
+       depends on ARM && KERNEL_MODE_NEON
+       select CRYPTO_ALGAPI
+       select CRYPTO_AES_ARM
+       select CRYPTO_ABLK_HELPER
+       help
+         Use a faster and more secure NEON based implementation of AES in CBC,
+         CTR and XTS modes
+
+         Bit sliced AES gives around 45% speedup on Cortex-A15 for CTR mode
+         and for XTS mode encryption, CBC and XTS mode decryption speedup is
+         around 25%. (CBC encryption speed is not affected by this driver.)
+         This implementation does not rely on any lookup tables so it is
+         believed to be invulnerable to cache timing attacks.
+
 config CRYPTO_ANUBIS
        tristate "Anubis cipher algorithm"
        select CRYPTO_ALGAPI
index f40acef80269fa9e6a38435b1c328a7c80552b34..a6977e12d5745ab5f2015e2f2879174bddd64bc0 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/ipmi.h>
 #include <linux/device.h>
 #include <linux/pnp.h>
+#include <linux/spinlock.h>
 
 MODULE_AUTHOR("Zhao Yakui");
 MODULE_DESCRIPTION("ACPI IPMI Opregion driver");
@@ -57,7 +58,7 @@ struct acpi_ipmi_device {
        struct list_head head;
        /* the IPMI request message list */
        struct list_head tx_msg_list;
-       struct mutex    tx_msg_lock;
+       spinlock_t      tx_msg_lock;
        acpi_handle handle;
        struct pnp_dev *pnp_dev;
        ipmi_user_t     user_interface;
@@ -147,6 +148,7 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg,
        struct kernel_ipmi_msg *msg;
        struct acpi_ipmi_buffer *buffer;
        struct acpi_ipmi_device *device;
+       unsigned long flags;
 
        msg = &tx_msg->tx_message;
        /*
@@ -177,10 +179,10 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg,
 
        /* Get the msgid */
        device = tx_msg->device;
-       mutex_lock(&device->tx_msg_lock);
+       spin_lock_irqsave(&device->tx_msg_lock, flags);
        device->curr_msgid++;
        tx_msg->tx_msgid = device->curr_msgid;
-       mutex_unlock(&device->tx_msg_lock);
+       spin_unlock_irqrestore(&device->tx_msg_lock, flags);
 }
 
 static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg,
@@ -242,6 +244,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
        int msg_found = 0;
        struct acpi_ipmi_msg *tx_msg;
        struct pnp_dev *pnp_dev = ipmi_device->pnp_dev;
+       unsigned long flags;
 
        if (msg->user != ipmi_device->user_interface) {
                dev_warn(&pnp_dev->dev, "Unexpected response is returned. "
@@ -250,7 +253,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
                ipmi_free_recv_msg(msg);
                return;
        }
-       mutex_lock(&ipmi_device->tx_msg_lock);
+       spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
        list_for_each_entry(tx_msg, &ipmi_device->tx_msg_list, head) {
                if (msg->msgid == tx_msg->tx_msgid) {
                        msg_found = 1;
@@ -258,7 +261,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
                }
        }
 
-       mutex_unlock(&ipmi_device->tx_msg_lock);
+       spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
        if (!msg_found) {
                dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is "
                        "returned.\n", msg->msgid);
@@ -378,6 +381,7 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
        struct acpi_ipmi_device *ipmi_device = handler_context;
        int err, rem_time;
        acpi_status status;
+       unsigned long flags;
        /*
         * IPMI opregion message.
         * IPMI message is firstly written to the BMC and system software
@@ -395,9 +399,9 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
                return AE_NO_MEMORY;
 
        acpi_format_ipmi_msg(tx_msg, address, value);
-       mutex_lock(&ipmi_device->tx_msg_lock);
+       spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
        list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list);
-       mutex_unlock(&ipmi_device->tx_msg_lock);
+       spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
        err = ipmi_request_settime(ipmi_device->user_interface,
                                        &tx_msg->addr,
                                        tx_msg->tx_msgid,
@@ -413,9 +417,9 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
        status = AE_OK;
 
 end_label:
-       mutex_lock(&ipmi_device->tx_msg_lock);
+       spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
        list_del(&tx_msg->head);
-       mutex_unlock(&ipmi_device->tx_msg_lock);
+       spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
        kfree(tx_msg);
        return status;
 }
@@ -457,7 +461,7 @@ static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device)
 
        INIT_LIST_HEAD(&ipmi_device->head);
 
-       mutex_init(&ipmi_device->tx_msg_lock);
+       spin_lock_init(&ipmi_device->tx_msg_lock);
        INIT_LIST_HEAD(&ipmi_device->tx_msg_list);
        ipmi_install_space_handler(ipmi_device);
 
index fbdb82e70d10623c0bbf94aa73723a40fd32e77d..407ad13cac2f27945c3b812f791a4f615c2db492 100644 (file)
@@ -968,7 +968,7 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
        }
        return 0;
 }
-EXPORT_SYMBOL_GPL(acpi_bus_get_device);
+EXPORT_SYMBOL(acpi_bus_get_device);
 
 int acpi_device_add(struct acpi_device *device,
                    void (*release)(struct device *))
@@ -1121,7 +1121,7 @@ int acpi_bus_register_driver(struct acpi_driver *driver)
 EXPORT_SYMBOL(acpi_bus_register_driver);
 
 /**
- * acpi_bus_unregister_driver - unregisters a driver with the APIC bus
+ * acpi_bus_unregister_driver - unregisters a driver with the ACPI bus
  * @driver: driver to unregister
  *
  * Unregisters a driver with the ACPI bus.  Searches the namespace for all
index c6707278a6bb496d200caf9f0bd4a57233b9b1a1..c4876ac9151a56bc95a05df647e0850cea3182c4 100644 (file)
@@ -552,7 +552,6 @@ amba_aphb_device_add(struct device *parent, const char *name,
        if (!dev)
                return ERR_PTR(-ENOMEM);
 
-       dev->dma_mask = dma_mask;
        dev->dev.coherent_dma_mask = dma_mask;
        dev->irq[0] = irq1;
        dev->irq[1] = irq2;
@@ -619,7 +618,7 @@ static void amba_device_initialize(struct amba_device *dev, const char *name)
                dev_set_name(&dev->dev, "%s", name);
        dev->dev.release = amba_device_release;
        dev->dev.bus = &amba_bustype;
-       dev->dev.dma_mask = &dev->dma_mask;
+       dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
        dev->res.name = dev_name(&dev->dev);
 }
 
@@ -663,9 +662,6 @@ int amba_device_register(struct amba_device *dev, struct resource *parent)
        amba_device_initialize(dev, dev->dev.init_name);
        dev->dev.init_name = NULL;
 
-       if (!dev->dev.coherent_dma_mask && dev->dma_mask)
-               dev_warn(&dev->dev, "coherent dma mask is unset\n");
-
        return amba_device_add(dev, parent);
 }
 
index 1ec53f8ca96fa682fc1492e61816c6b043876f7d..ddf470c2341d7f1f153b7d7776fa873b9c7906f3 100644 (file)
@@ -144,6 +144,7 @@ static int ixp4xx_pata_probe(struct platform_device *pdev)
        struct ata_host *host;
        struct ata_port *ap;
        struct ixp4xx_pata_data *data = dev_get_platdata(&pdev->dev);
+       int ret;
 
        cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -157,7 +158,9 @@ static int ixp4xx_pata_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        /* acquire resources and fill host */
-       pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        data->cs0 = devm_ioremap(&pdev->dev, cs0->start, 0x1000);
        data->cs1 = devm_ioremap(&pdev->dev, cs1->start, 0x1000);
index c51bbb9ea8e8a826e3d2fa68e693d1cf6a3a2a94..6231d4394f45d021c8dc7cf8a15a38c14e29b2c7 100644 (file)
@@ -1014,8 +1014,9 @@ static int octeon_cf_probe(struct platform_device *pdev)
        }
        cf_port->c0 = ap->ioaddr.ctl_addr;
 
-       pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64);
-       pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+       rv = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+       if (rv)
+               return ret;
 
        ata_port_desc(ap, "cmd %p ctl %p", base, ap->ioaddr.ctl_addr);
 
index 958ba2a420c34b0e5411b116d639214e700f5c47..97f4acb54ad626795972ffb8e35572101d05d08d 100644 (file)
@@ -2,7 +2,7 @@
  *  sata_promise.c - Promise SATA
  *
  *  Maintained by:  Tejun Heo <tj@kernel.org>
- *                 Mikael Pettersson <mikpe@it.uu.se>
+ *                 Mikael Pettersson
  *                 Please ALWAYS copy linux-ide@vger.kernel.org
  *                 on emails.
  *
index 449f6298dc8937a437ec1f7c4ab6283db3289c40..8557adcd34ee88a82cfb9a805859cba5ad79bef2 100644 (file)
@@ -2865,15 +2865,4 @@ static struct pci_driver he_driver = {
        .id_table =     he_pci_tbl,
 };
 
-static int __init he_init(void)
-{
-       return pci_register_driver(&he_driver);
-}
-
-static void __exit he_cleanup(void)
-{
-       pci_unregister_driver(&he_driver);
-}
-
-module_init(he_init);
-module_exit(he_cleanup);
+module_pci_driver(he_driver);
index 409502a78e7ebcc964ed1ae3cf4500b1c92139a8..5aca5f4c545896c567c892716a64b6cb22452b43 100644 (file)
@@ -778,7 +778,7 @@ static int ns_init_card(int i, struct pci_dev *pcidev)
                return error;
        }
 
-       if (mac[i] == NULL || mac_pton(mac[i], card->atmdev->esi)) {
+       if (mac[i] == NULL || !mac_pton(mac[i], card->atmdev->esi)) {
                nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET,
                                   card->atmdev->esi, 6);
                if (memcmp(card->atmdev->esi, "\x00\x00\x00\x00\x00\x00", 6) ==
index c7cfadcf67521d82f7d977979631e4805f5a31e9..34abf4d8a45ff4f3f6d25787887a8bc787779133 100644 (file)
@@ -2017,7 +2017,7 @@ EXPORT_SYMBOL_GPL(device_move);
  */
 void device_shutdown(void)
 {
-       struct device *dev;
+       struct device *dev, *parent;
 
        spin_lock(&devices_kset->list_lock);
        /*
@@ -2034,7 +2034,7 @@ void device_shutdown(void)
                 * prevent it from being freed because parent's
                 * lock is to be held
                 */
-               get_device(dev->parent);
+               parent = get_device(dev->parent);
                get_device(dev);
                /*
                 * Make sure the device is off the kset list, in the
@@ -2044,8 +2044,8 @@ void device_shutdown(void)
                spin_unlock(&devices_kset->list_lock);
 
                /* hold lock to avoid race with probe/release */
-               if (dev->parent)
-                       device_lock(dev->parent);
+               if (parent)
+                       device_lock(parent);
                device_lock(dev);
 
                /* Don't allow any more runtime suspends */
@@ -2063,11 +2063,11 @@ void device_shutdown(void)
                }
 
                device_unlock(dev);
-               if (dev->parent)
-                       device_unlock(dev->parent);
+               if (parent)
+                       device_unlock(parent);
 
                put_device(dev);
-               put_device(dev->parent);
+               put_device(parent);
 
                spin_lock(&devices_kset->list_lock);
        }
index c9fd6943ce456a1123e58106b0f028418d535fdd..50329d1057ed5dc5c929fde89237add36c55ea48 100644 (file)
@@ -210,25 +210,6 @@ static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc)
        }
 }
 
-static void bcma_core_pci_power_save(struct bcma_drv_pci *pc, bool up)
-{
-       u16 data;
-
-       if (pc->core->id.rev >= 15 && pc->core->id.rev <= 20) {
-               data = up ? 0x74 : 0x7C;
-               bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
-                                        BCMA_CORE_PCI_MDIO_BLK1_MGMT1, 0x7F64);
-               bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
-                                        BCMA_CORE_PCI_MDIO_BLK1_MGMT3, data);
-       } else if (pc->core->id.rev >= 21 && pc->core->id.rev <= 22) {
-               data = up ? 0x75 : 0x7D;
-               bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
-                                        BCMA_CORE_PCI_MDIO_BLK1_MGMT1, 0x7E65);
-               bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
-                                        BCMA_CORE_PCI_MDIO_BLK1_MGMT3, data);
-       }
-}
-
 /**************************************************
  * Init.
  **************************************************/
@@ -255,6 +236,32 @@ void bcma_core_pci_init(struct bcma_drv_pci *pc)
                bcma_core_pci_clientmode_init(pc);
 }
 
+void bcma_core_pci_power_save(struct bcma_bus *bus, bool up)
+{
+       struct bcma_drv_pci *pc;
+       u16 data;
+
+       if (bus->hosttype != BCMA_HOSTTYPE_PCI)
+               return;
+
+       pc = &bus->drv_pci[0];
+
+       if (pc->core->id.rev >= 15 && pc->core->id.rev <= 20) {
+               data = up ? 0x74 : 0x7C;
+               bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
+                                        BCMA_CORE_PCI_MDIO_BLK1_MGMT1, 0x7F64);
+               bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
+                                        BCMA_CORE_PCI_MDIO_BLK1_MGMT3, data);
+       } else if (pc->core->id.rev >= 21 && pc->core->id.rev <= 22) {
+               data = up ? 0x75 : 0x7D;
+               bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
+                                        BCMA_CORE_PCI_MDIO_BLK1_MGMT1, 0x7E65);
+               bcma_pcie_mdio_writeread(pc, BCMA_CORE_PCI_MDIO_BLK1,
+                                        BCMA_CORE_PCI_MDIO_BLK1_MGMT3, data);
+       }
+}
+EXPORT_SYMBOL_GPL(bcma_core_pci_power_save);
+
 int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
                          bool enable)
 {
@@ -310,8 +317,6 @@ void bcma_core_pci_up(struct bcma_bus *bus)
 
        pc = &bus->drv_pci[0];
 
-       bcma_core_pci_power_save(pc, true);
-
        bcma_core_pci_extend_L1timer(pc, true);
 }
 EXPORT_SYMBOL_GPL(bcma_core_pci_up);
@@ -326,7 +331,5 @@ void bcma_core_pci_down(struct bcma_bus *bus)
        pc = &bus->drv_pci[0];
 
        bcma_core_pci_extend_L1timer(pc, false);
-
-       bcma_core_pci_power_save(pc, false);
 }
 EXPORT_SYMBOL_GPL(bcma_core_pci_down);
index cd6b20fce680591a5253f15546cae34d21a4bb68..37768401d1139f0cfa73ed3e6210ce892a5e91cc 100644 (file)
@@ -269,6 +269,8 @@ static struct bcma_device *bcma_find_core_reverse(struct bcma_bus *bus, u16 core
        return NULL;
 }
 
+#define IS_ERR_VALUE_U32(x) ((x) >= (u32)-MAX_ERRNO)
+
 static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
                              struct bcma_device_id *match, int core_num,
                              struct bcma_device *core)
@@ -351,11 +353,11 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
         * the main register space for the core
         */
        tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SLAVE, 0);
-       if (tmp == 0 || IS_ERR_VALUE(tmp)) {
+       if (tmp == 0 || IS_ERR_VALUE_U32(tmp)) {
                /* Try again to see if it is a bridge */
                tmp = bcma_erom_get_addr_desc(bus, eromptr,
                                              SCAN_ADDR_TYPE_BRIDGE, 0);
-               if (tmp == 0 || IS_ERR_VALUE(tmp)) {
+               if (tmp == 0 || IS_ERR_VALUE_U32(tmp)) {
                        return -EILSEQ;
                } else {
                        bcma_info(bus, "Bridge found\n");
@@ -369,7 +371,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
                for (j = 0; ; j++) {
                        tmp = bcma_erom_get_addr_desc(bus, eromptr,
                                SCAN_ADDR_TYPE_SLAVE, i);
-                       if (IS_ERR_VALUE(tmp)) {
+                       if (IS_ERR_VALUE_U32(tmp)) {
                                /* no more entries for port _i_ */
                                /* pr_debug("erom: slave port %d "
                                 * "has %d descriptors\n", i, j); */
@@ -386,7 +388,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
                for (j = 0; ; j++) {
                        tmp = bcma_erom_get_addr_desc(bus, eromptr,
                                SCAN_ADDR_TYPE_MWRAP, i);
-                       if (IS_ERR_VALUE(tmp)) {
+                       if (IS_ERR_VALUE_U32(tmp)) {
                                /* no more entries for port _i_ */
                                /* pr_debug("erom: master wrapper %d "
                                 * "has %d descriptors\n", i, j); */
@@ -404,7 +406,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
                for (j = 0; ; j++) {
                        tmp = bcma_erom_get_addr_desc(bus, eromptr,
                                SCAN_ADDR_TYPE_SWRAP, i + hack);
-                       if (IS_ERR_VALUE(tmp)) {
+                       if (IS_ERR_VALUE_U32(tmp)) {
                                /* no more entries for port _i_ */
                                /* pr_debug("erom: master wrapper %d "
                                 * has %d descriptors\n", i, j); */
index d2d95ff5353b08a4f49d1c3da4179090751851bf..edfa2515bc8613f952c448194bfcebf7835d75c1 100644 (file)
@@ -1189,6 +1189,7 @@ static int cciss_ioctl32_passthru(struct block_device *bdev, fmode_t mode,
        int err;
        u32 cp;
 
+       memset(&arg64, 0, sizeof(arg64));
        err = 0;
        err |=
            copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
index 639d26b90b9117a56c69f991663f603847cc206c..2b944038453681ef15ba61f41e1cfa3a9e885fbe 100644 (file)
@@ -1193,6 +1193,7 @@ out_passthru:
                ida_pci_info_struct pciinfo;
 
                if (!arg) return -EINVAL;
+               memset(&pciinfo, 0, sizeof(pciinfo));
                pciinfo.bus = host->pci_dev->bus->number;
                pciinfo.dev_fn = host->pci_dev->devfn;
                pciinfo.board_id = host->board_id;
index da52092980e2312987b6a1040df5c0ba444852c3..26d03fa0bf26696d9e004b3983a580d409d3d006 100644 (file)
@@ -1949,12 +1949,9 @@ static int nvme_dev_map(struct nvme_dev *dev)
        if (pci_request_selected_regions(pdev, bars, "nvme"))
                goto disable_pci;
 
-       if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)))
-               dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
-       else if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)))
-               dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
-       else
-               goto disable_pci;
+       if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) &&
+           dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)))
+               goto disable;
 
        pci_set_drvdata(pdev, dev);
        dev->bar = ioremap(pci_resource_start(pdev, 0), 8192);
@@ -2168,6 +2165,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        INIT_LIST_HEAD(&dev->namespaces);
        dev->pci_dev = pdev;
+
        result = nvme_set_instance(dev);
        if (result)
                goto free;
index b22a7d0fe5b72134c392a34d64b73e668f4485d4..cb1db2979d3d7b5417a8a4b131e09c5c5f6767c0 100644 (file)
@@ -931,12 +931,14 @@ static const char *rbd_dev_v1_snap_name(struct rbd_device *rbd_dev,
                                        u64 snap_id)
 {
        u32 which;
+       const char *snap_name;
 
        which = rbd_dev_snap_index(rbd_dev, snap_id);
        if (which == BAD_SNAP_INDEX)
-               return NULL;
+               return ERR_PTR(-ENOENT);
 
-       return _rbd_dev_v1_snap_name(rbd_dev, which);
+       snap_name = _rbd_dev_v1_snap_name(rbd_dev, which);
+       return snap_name ? snap_name : ERR_PTR(-ENOMEM);
 }
 
 static const char *rbd_snap_name(struct rbd_device *rbd_dev, u64 snap_id)
@@ -2812,7 +2814,7 @@ out_err:
        obj_request_done_set(obj_request);
 }
 
-static int rbd_obj_notify_ack(struct rbd_device *rbd_dev, u64 notify_id)
+static int rbd_obj_notify_ack_sync(struct rbd_device *rbd_dev, u64 notify_id)
 {
        struct rbd_obj_request *obj_request;
        struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
@@ -2827,16 +2829,17 @@ static int rbd_obj_notify_ack(struct rbd_device *rbd_dev, u64 notify_id)
        obj_request->osd_req = rbd_osd_req_create(rbd_dev, false, obj_request);
        if (!obj_request->osd_req)
                goto out;
-       obj_request->callback = rbd_obj_request_put;
 
        osd_req_op_watch_init(obj_request->osd_req, 0, CEPH_OSD_OP_NOTIFY_ACK,
                                        notify_id, 0, 0);
        rbd_osd_req_format_read(obj_request);
 
        ret = rbd_obj_request_submit(osdc, obj_request);
-out:
        if (ret)
-               rbd_obj_request_put(obj_request);
+               goto out;
+       ret = rbd_obj_request_wait(obj_request);
+out:
+       rbd_obj_request_put(obj_request);
 
        return ret;
 }
@@ -2856,7 +2859,7 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data)
        if (ret)
                rbd_warn(rbd_dev, "header refresh error (%d)\n", ret);
 
-       rbd_obj_notify_ack(rbd_dev, notify_id);
+       rbd_obj_notify_ack_sync(rbd_dev, notify_id);
 }
 
 /*
@@ -3328,6 +3331,31 @@ static void rbd_exists_validate(struct rbd_device *rbd_dev)
                clear_bit(RBD_DEV_FLAG_EXISTS, &rbd_dev->flags);
 }
 
+static void rbd_dev_update_size(struct rbd_device *rbd_dev)
+{
+       sector_t size;
+       bool removing;
+
+       /*
+        * Don't hold the lock while doing disk operations,
+        * or lock ordering will conflict with the bdev mutex via:
+        * rbd_add() -> blkdev_get() -> rbd_open()
+        */
+       spin_lock_irq(&rbd_dev->lock);
+       removing = test_bit(RBD_DEV_FLAG_REMOVING, &rbd_dev->flags);
+       spin_unlock_irq(&rbd_dev->lock);
+       /*
+        * If the device is being removed, rbd_dev->disk has
+        * been destroyed, so don't try to update its size
+        */
+       if (!removing) {
+               size = (sector_t)rbd_dev->mapping.size / SECTOR_SIZE;
+               dout("setting size to %llu sectors", (unsigned long long)size);
+               set_capacity(rbd_dev->disk, size);
+               revalidate_disk(rbd_dev->disk);
+       }
+}
+
 static int rbd_dev_refresh(struct rbd_device *rbd_dev)
 {
        u64 mapping_size;
@@ -3347,12 +3375,7 @@ static int rbd_dev_refresh(struct rbd_device *rbd_dev)
        up_write(&rbd_dev->header_rwsem);
 
        if (mapping_size != rbd_dev->mapping.size) {
-               sector_t size;
-
-               size = (sector_t)rbd_dev->mapping.size / SECTOR_SIZE;
-               dout("setting size to %llu sectors", (unsigned long long)size);
-               set_capacity(rbd_dev->disk, size);
-               revalidate_disk(rbd_dev->disk);
+               rbd_dev_update_size(rbd_dev);
        }
 
        return ret;
@@ -4061,8 +4084,13 @@ static u64 rbd_v2_snap_id_by_name(struct rbd_device *rbd_dev, const char *name)
 
                snap_id = snapc->snaps[which];
                snap_name = rbd_dev_v2_snap_name(rbd_dev, snap_id);
-               if (IS_ERR(snap_name))
-                       break;
+               if (IS_ERR(snap_name)) {
+                       /* ignore no-longer existing snapshots */
+                       if (PTR_ERR(snap_name) == -ENOENT)
+                               continue;
+                       else
+                               break;
+               }
                found = !strcmp(name, snap_name);
                kfree(snap_name);
        }
@@ -4141,8 +4169,8 @@ static int rbd_dev_spec_update(struct rbd_device *rbd_dev)
        /* Look up the snapshot name, and make a copy */
 
        snap_name = rbd_snap_name(rbd_dev, spec->snap_id);
-       if (!snap_name) {
-               ret = -ENOMEM;
+       if (IS_ERR(snap_name)) {
+               ret = PTR_ERR(snap_name);
                goto out_err;
        }
 
@@ -5163,10 +5191,23 @@ static ssize_t rbd_remove(struct bus_type *bus,
        if (ret < 0 || already)
                return ret;
 
-       rbd_bus_del_dev(rbd_dev);
        ret = rbd_dev_header_watch_sync(rbd_dev, false);
        if (ret)
                rbd_warn(rbd_dev, "failed to cancel watch event (%d)\n", ret);
+
+       /*
+        * flush remaining watch callbacks - these must be complete
+        * before the osd_client is shutdown
+        */
+       dout("%s: flushing notifies", __func__);
+       ceph_osdc_flush_notifies(&rbd_dev->rbd_client->client->osdc);
+       /*
+        * Don't free anything from rbd_dev->disk until after all
+        * notifies are completely processed. Otherwise
+        * rbd_bus_del_dev() will race with rbd_watch_cb(), resulting
+        * in a potential use after free of rbd_dev->disk or rbd_dev.
+        */
+       rbd_bus_del_dev(rbd_dev);
        rbd_dev_image_release(rbd_dev);
        module_put(THIS_MODULE);
 
index a12b923bbaca91f14b923e0b271b00ebc1be8d28..0a327f4154a2b2039ad4ae0e50b7195dfa2cb5f0 100644 (file)
@@ -85,6 +85,7 @@ static struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x04CA, 0x3008) },
        { USB_DEVICE(0x13d3, 0x3362) },
        { USB_DEVICE(0x0CF3, 0xE004) },
+       { USB_DEVICE(0x0CF3, 0xE005) },
        { USB_DEVICE(0x0930, 0x0219) },
        { USB_DEVICE(0x0489, 0xe057) },
        { USB_DEVICE(0x13d3, 0x3393) },
@@ -126,6 +127,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
index 8e16f0af6358872606fbe102bddc9ade2c6ab470..f3dfc0a88fdcb95e25647caa6cfc14a1d9a5a484 100644 (file)
@@ -102,6 +102,7 @@ static struct usb_device_id btusb_table[] = {
 
        /* Broadcom BCM20702A0 */
        { USB_DEVICE(0x0b05, 0x17b5) },
+       { USB_DEVICE(0x0b05, 0x17cb) },
        { USB_DEVICE(0x04ca, 0x2003) },
        { USB_DEVICE(0x0489, 0xe042) },
        { USB_DEVICE(0x413c, 0x8197) },
@@ -112,6 +113,9 @@ static struct usb_device_id btusb_table[] = {
        /*Broadcom devices with vendor specific id */
        { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
 
+       /* Belkin F8065bf - Broadcom based */
+       { USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
+
        { }     /* Terminating entry */
 };
 
@@ -148,6 +152,7 @@ static struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
index 19ab6ff53d59776cedc592a5b18c2fba8fe02a65..2394e9753ef56b47e93d91bd7499eeb657c51383 100644 (file)
@@ -700,6 +700,7 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
                                         phys_addr_t sdramwins_phys_base,
                                         size_t sdramwins_size)
 {
+       struct device_node *np;
        int win;
 
        mbus->mbuswins_base = ioremap(mbuswins_phys_base, mbuswins_size);
@@ -712,8 +713,11 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
                return -ENOMEM;
        }
 
-       if (of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric"))
+       np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric");
+       if (np) {
                mbus->hw_io_coherency = 1;
+               of_node_put(np);
+       }
 
        for (win = 0; win < mbus->soc->num_wins; win++)
                mvebu_mbus_disable_window(mbus, win);
@@ -861,11 +865,13 @@ static void __init mvebu_mbus_get_pcie_resources(struct device_node *np,
        int ret;
 
        /*
-        * These are optional, so we clear them and they'll
-        * be zero if they are missing from the DT.
+        * These are optional, so we make sure that resource_size(x) will
+        * return 0.
         */
        memset(mem, 0, sizeof(struct resource));
+       mem->end = -1;
        memset(io, 0, sizeof(struct resource));
+       io->end = -1;
 
        ret = of_property_read_u32_array(np, "pcie-mem-aperture", reg, ARRAY_SIZE(reg));
        if (!ret) {
index 7a7929ba26588dbf07d014bf8bb3cf8f55da509a..06189e55b4e5a0479d2eaab0a31610ef91bf472f 100644 (file)
@@ -142,32 +142,6 @@ static int vtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
        return length;
 }
 
-ssize_t tpm_show_locality(struct device *dev, struct device_attribute *attr,
-                         char *buf)
-{
-       struct tpm_chip *chip = dev_get_drvdata(dev);
-       struct tpm_private *priv = TPM_VPRIV(chip);
-       u8 locality = priv->shr->locality;
-
-       return sprintf(buf, "%d\n", locality);
-}
-
-ssize_t tpm_store_locality(struct device *dev, struct device_attribute *attr,
-                       const char *buf, size_t len)
-{
-       struct tpm_chip *chip = dev_get_drvdata(dev);
-       struct tpm_private *priv = TPM_VPRIV(chip);
-       u8 val;
-
-       int rv = kstrtou8(buf, 0, &val);
-       if (rv)
-               return rv;
-
-       priv->shr->locality = val;
-
-       return len;
-}
-
 static const struct file_operations vtpm_ops = {
        .owner = THIS_MODULE,
        .llseek = no_llseek,
@@ -188,8 +162,6 @@ static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
 static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
 static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL);
 static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
-static DEVICE_ATTR(locality, S_IRUGO | S_IWUSR, tpm_show_locality,
-               tpm_store_locality);
 
 static struct attribute *vtpm_attrs[] = {
        &dev_attr_pubek.attr,
@@ -202,7 +174,6 @@ static struct attribute *vtpm_attrs[] = {
        &dev_attr_cancel.attr,
        &dev_attr_durations.attr,
        &dev_attr_timeouts.attr,
-       &dev_attr_locality.attr,
        NULL,
 };
 
@@ -210,8 +181,6 @@ static struct attribute_group vtpm_attr_grp = {
        .attrs = vtpm_attrs,
 };
 
-#define TPM_LONG_TIMEOUT   (10 * 60 * HZ)
-
 static const struct tpm_vendor_specific tpm_vtpm = {
        .status = vtpm_status,
        .recv = vtpm_recv,
@@ -224,11 +193,6 @@ static const struct tpm_vendor_specific tpm_vtpm = {
        .miscdev = {
                .fops = &vtpm_ops,
        },
-       .duration = {
-               TPM_LONG_TIMEOUT,
-               TPM_LONG_TIMEOUT,
-               TPM_LONG_TIMEOUT,
-       },
 };
 
 static irqreturn_t tpmif_interrupt(int dummy, void *dev_id)
index 41c69469ce2000ec223170970c856a2287f10db2..971d796e071d889c290029ada3b2dc862f10fcbb 100644 (file)
@@ -26,6 +26,7 @@ config DW_APB_TIMER_OF
 
 config ARMADA_370_XP_TIMER
        bool
+       select CLKSRC_OF
 
 config ORION_TIMER
        select CLKSRC_OF
index 37f5325bec95936260c50b2a099ccc7fb000ba53..b9ddd9e3a2f599e2cc7424c1eac18d4280b2f850 100644 (file)
@@ -30,6 +30,9 @@ void __init clocksource_of_init(void)
        clocksource_of_init_fn init_func;
 
        for_each_matching_node_and_match(np, __clksrc_of_table, &match) {
+               if (!of_device_is_available(np))
+                       continue;
+
                init_func = match->data;
                init_func(np);
        }
index b9c81b7c3a3bfa5a251129e42c687b1e0aeeb851..3a5909c12d420dbbb6f54f011882303ba4a48a62 100644 (file)
@@ -301,7 +301,7 @@ static void em_sti_register_clockevent(struct em_sti_priv *p)
        ced->name = dev_name(&p->pdev->dev);
        ced->features = CLOCK_EVT_FEAT_ONESHOT;
        ced->rating = 200;
-       ced->cpumask = cpumask_of(0);
+       ced->cpumask = cpu_possible_mask;
        ced->set_next_event = em_sti_clock_event_next;
        ced->set_mode = em_sti_clock_event_mode;
 
index 5b34768f4d7c79f68253966acc8e8268e53f318e..62b0de6a18370fade34eca20205557bd5871cc3a 100644 (file)
@@ -428,7 +428,6 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt)
                                evt->irq);
                        return -EIO;
                }
-               irq_set_affinity(evt->irq, cpumask_of(cpu));
        } else {
                enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0);
        }
@@ -449,6 +448,7 @@ static int exynos4_mct_cpu_notify(struct notifier_block *self,
                                           unsigned long action, void *hcpu)
 {
        struct mct_clock_event_device *mevt;
+       unsigned int cpu;
 
        /*
         * Grab cpu pointer in each case to avoid spurious
@@ -459,6 +459,12 @@ static int exynos4_mct_cpu_notify(struct notifier_block *self,
                mevt = this_cpu_ptr(&percpu_mct_tick);
                exynos4_local_timer_setup(&mevt->evt);
                break;
+       case CPU_ONLINE:
+               cpu = (unsigned long)hcpu;
+               if (mct_int_type == MCT_INT_SPI)
+                       irq_set_affinity(mct_irqs[MCT_L0_IRQ + cpu],
+                                               cpumask_of(cpu));
+               break;
        case CPU_DYING:
                mevt = this_cpu_ptr(&percpu_mct_tick);
                exynos4_local_timer_stop(&mevt->evt);
@@ -500,6 +506,8 @@ static void __init exynos4_timer_resources(struct device_node *np, void __iomem
                                         &percpu_mct_tick);
                WARN(err, "MCT: can't request IRQ %d (%d)\n",
                     mct_irqs[MCT_L0_IRQ], err);
+       } else {
+               irq_set_affinity(mct_irqs[MCT_L0_IRQ], cpumask_of(0));
        }
 
        err = register_cpu_notifier(&exynos4_mct_cpu_nb);
index a1260b4549db647336192d24b3471b6b627897af..d2c3253e015ee23f107d2d34333c6afa533ab7cf 100644 (file)
@@ -986,6 +986,10 @@ static int __init acpi_cpufreq_init(void)
 {
        int ret;
 
+       /* don't keep reloading if cpufreq_driver exists */
+       if (cpufreq_get_current_driver())
+               return 0;
+
        if (acpi_disabled)
                return 0;
 
index cbfffa91ebdd46054d21f5c4138909b549787b06..c522a95c0e168ae30e4a347f189f89c27173c427 100644 (file)
@@ -12,6 +12,7 @@
 #define pr_fmt(fmt)    KBUILD_MODNAME ": " fmt
 
 #include <linux/clk.h>
+#include <linux/cpu.h>
 #include <linux/cpufreq.h>
 #include <linux/err.h>
 #include <linux/module.h>
@@ -177,7 +178,11 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
        struct device_node *np;
        int ret;
 
-       cpu_dev = &pdev->dev;
+       cpu_dev = get_cpu_device(0);
+       if (!cpu_dev) {
+               pr_err("failed to get cpu0 device\n");
+               return -ENODEV;
+       }
 
        np = of_node_get(cpu_dev->of_node);
        if (!np) {
@@ -224,7 +229,7 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
        if (of_property_read_u32(np, "clock-latency", &transition_latency))
                transition_latency = CPUFREQ_ETERNAL;
 
-       if (cpu_reg) {
+       if (!IS_ERR(cpu_reg)) {
                struct opp *opp;
                unsigned long min_uV, max_uV;
                int i;
index 43c24aa756f6f29935af8eb0614945a442a36a19..04548f7023af68dee6b36fc590ec59f02c0216f7 100644 (file)
@@ -952,9 +952,20 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
        if (cpu == policy->cpu)
                return;
 
+       /*
+        * Take direct locks as lock_policy_rwsem_write wouldn't work here.
+        * Also lock for last cpu is enough here as contention will happen only
+        * after policy->cpu is changed and after it is changed, other threads
+        * will try to acquire lock for new cpu. And policy is already updated
+        * by then.
+        */
+       down_write(&per_cpu(cpu_policy_rwsem, policy->cpu));
+
        policy->last_cpu = policy->cpu;
        policy->cpu = cpu;
 
+       up_write(&per_cpu(cpu_policy_rwsem, policy->last_cpu));
+
 #ifdef CONFIG_CPU_FREQ_TABLE
        cpufreq_frequency_table_update_policy_cpu(policy);
 #endif
@@ -1125,7 +1136,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
        int ret;
 
        /* first sibling now owns the new sysfs dir */
-       cpu_dev = get_cpu_device(cpumask_first(policy->cpus));
+       cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu));
 
        /* Don't touch sysfs files during light-weight tear-down */
        if (frozen)
@@ -1189,12 +1200,9 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
                        policy->governor->name, CPUFREQ_NAME_LEN);
 #endif
 
-       WARN_ON(lock_policy_rwsem_write(cpu));
+       lock_policy_rwsem_read(cpu);
        cpus = cpumask_weight(policy->cpus);
-
-       if (cpus > 1)
-               cpumask_clear_cpu(cpu, policy->cpus);
-       unlock_policy_rwsem_write(cpu);
+       unlock_policy_rwsem_read(cpu);
 
        if (cpu != policy->cpu) {
                if (!frozen)
@@ -1203,9 +1211,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
 
                new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu, frozen);
                if (new_cpu >= 0) {
-                       WARN_ON(lock_policy_rwsem_write(cpu));
                        update_policy_cpu(policy, new_cpu);
-                       unlock_policy_rwsem_write(cpu);
 
                        if (!frozen) {
                                pr_debug("%s: policy Kobject moved to cpu: %d "
@@ -1237,9 +1243,12 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
                return -EINVAL;
        }
 
-       lock_policy_rwsem_read(cpu);
+       WARN_ON(lock_policy_rwsem_write(cpu));
        cpus = cpumask_weight(policy->cpus);
-       unlock_policy_rwsem_read(cpu);
+
+       if (cpus > 1)
+               cpumask_clear_cpu(cpu, policy->cpus);
+       unlock_policy_rwsem_write(cpu);
 
        /* If cpu is last user of policy, free policy */
        if (cpus == 1) {
@@ -1451,6 +1460,9 @@ unsigned int cpufreq_get(unsigned int cpu)
 {
        unsigned int ret_freq = 0;
 
+       if (cpufreq_disabled() || !cpufreq_driver)
+               return -ENOENT;
+
        if (!down_read_trylock(&cpufreq_rwsem))
                return 0;
 
@@ -2095,7 +2107,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
        write_lock_irqsave(&cpufreq_driver_lock, flags);
        if (cpufreq_driver) {
                write_unlock_irqrestore(&cpufreq_driver_lock, flags);
-               return -EBUSY;
+               return -EEXIST;
        }
        cpufreq_driver = driver_data;
        write_unlock_irqrestore(&cpufreq_driver_lock, flags);
index d514c152fd1a43041e8ff570fca7f9cc2b28f58d..be5380ecdcd43f95c4aa88a62389c184597f3971 100644 (file)
@@ -457,7 +457,7 @@ err_free_table:
        opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
 err_put_node:
        of_node_put(np);
-       dev_err(dvfs_info->dev, "%s: failed initialization\n", __func__);
+       dev_err(&pdev->dev, "%s: failed initialization\n", __func__);
        return ret;
 }
 
index 3e396543aea4f74bb6b2d54e5a839eedf43a2c1a..c3fd2a101ca02852c677d021c567b27ee74b075a 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/cpu.h>
 #include <linux/cpufreq.h>
 #include <linux/delay.h>
 #include <linux/err.h>
@@ -202,7 +203,11 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
        unsigned long min_volt, max_volt;
        int num, ret;
 
-       cpu_dev = &pdev->dev;
+       cpu_dev = get_cpu_device(0);
+       if (!cpu_dev) {
+               pr_err("failed to get cpu0 device\n");
+               return -ENODEV;
+       }
 
        np = of_node_get(cpu_dev->of_node);
        if (!np) {
index 9733f29ed148f840a35171df38e32cbd1ce7bca8..32b3479a24051d09a0c1c53647b74848fcb3c967 100644 (file)
@@ -394,7 +394,10 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
        trace_cpu_frequency(pstate * 100000, cpu->cpu);
 
        cpu->pstate.current_pstate = pstate;
-       wrmsrl(MSR_IA32_PERF_CTL, pstate << 8);
+       if (limits.no_turbo)
+               wrmsrl(MSR_IA32_PERF_CTL, BIT(32) | (pstate << 8));
+       else
+               wrmsrl(MSR_IA32_PERF_CTL, pstate << 8);
 
 }
 
index 19e364fa59559cd6bf3e0ec77d9e5bb7c391aafa..3f418166ce02b8fc57a664f3d870bfb8508f3018 100644 (file)
@@ -113,7 +113,7 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy,
                unsigned int target_freq, unsigned int relation)
 {
        struct cpufreq_freqs freqs;
-       unsigned long newfreq;
+       long newfreq;
        struct clk *srcclk;
        int index, ret, mult = 1;
 
index 21180d6cad6e27f2f316a04b1e98fb2e61ac90d3..214357e12dc0b5469bb3c9daae5904ef3a618845 100644 (file)
@@ -218,23 +218,9 @@ static dma_addr_t crypt_phys;
 
 static int support_aes = 1;
 
-static void dev_release(struct device *dev)
-{
-       return;
-}
-
 #define DRIVER_NAME "ixp4xx_crypto"
-static struct platform_device pseudo_dev = {
-       .name = DRIVER_NAME,
-       .id   = 0,
-       .num_resources = 0,
-       .dev  = {
-               .coherent_dma_mask = DMA_BIT_MASK(32),
-               .release = dev_release,
-       }
-};
 
-static struct device *dev = &pseudo_dev.dev;
+static struct platform_device *pdev;
 
 static inline dma_addr_t crypt_virt2phys(struct crypt_ctl *virt)
 {
@@ -263,6 +249,7 @@ static inline const struct ix_hash_algo *ix_hash(struct crypto_tfm *tfm)
 
 static int setup_crypt_desc(void)
 {
+       struct device *dev = &pdev->dev;
        BUILD_BUG_ON(sizeof(struct crypt_ctl) != 64);
        crypt_virt = dma_alloc_coherent(dev,
                        NPE_QLEN * sizeof(struct crypt_ctl),
@@ -363,6 +350,7 @@ static void finish_scattered_hmac(struct crypt_ctl *crypt)
 
 static void one_packet(dma_addr_t phys)
 {
+       struct device *dev = &pdev->dev;
        struct crypt_ctl *crypt;
        struct ixp_ctx *ctx;
        int failed;
@@ -432,7 +420,7 @@ static void crypto_done_action(unsigned long arg)
        tasklet_schedule(&crypto_done_tasklet);
 }
 
-static int init_ixp_crypto(void)
+static int init_ixp_crypto(struct device *dev)
 {
        int ret = -ENODEV;
        u32 msg[2] = { 0, 0 };
@@ -519,7 +507,7 @@ err:
        return ret;
 }
 
-static void release_ixp_crypto(void)
+static void release_ixp_crypto(struct device *dev)
 {
        qmgr_disable_irq(RECV_QID);
        tasklet_kill(&crypto_done_tasklet);
@@ -886,6 +874,7 @@ static int ablk_perform(struct ablkcipher_request *req, int encrypt)
        enum dma_data_direction src_direction = DMA_BIDIRECTIONAL;
        struct ablk_ctx *req_ctx = ablkcipher_request_ctx(req);
        struct buffer_desc src_hook;
+       struct device *dev = &pdev->dev;
        gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
                                GFP_KERNEL : GFP_ATOMIC;
 
@@ -1010,6 +999,7 @@ static int aead_perform(struct aead_request *req, int encrypt,
        unsigned int cryptlen;
        struct buffer_desc *buf, src_hook;
        struct aead_ctx *req_ctx = aead_request_ctx(req);
+       struct device *dev = &pdev->dev;
        gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
                                GFP_KERNEL : GFP_ATOMIC;
 
@@ -1418,20 +1408,30 @@ static struct ixp_alg ixp4xx_algos[] = {
 } };
 
 #define IXP_POSTFIX "-ixp4xx"
+
+static const struct platform_device_info ixp_dev_info __initdata = {
+       .name           = DRIVER_NAME,
+       .id             = 0,
+       .dma_mask       = DMA_BIT_MASK(32),
+};
+
 static int __init ixp_module_init(void)
 {
        int num = ARRAY_SIZE(ixp4xx_algos);
-       int i,err ;
+       int i, err ;
 
-       if (platform_device_register(&pseudo_dev))
-               return -ENODEV;
+       pdev = platform_device_register_full(&ixp_dev_info);
+       if (IS_ERR(pdev))
+               return PTR_ERR(pdev);
+
+       dev = &pdev->dev;
 
        spin_lock_init(&desc_lock);
        spin_lock_init(&emerg_lock);
 
-       err = init_ixp_crypto();
+       err = init_ixp_crypto(&pdev->dev);
        if (err) {
-               platform_device_unregister(&pseudo_dev);
+               platform_device_unregister(pdev);
                return err;
        }
        for (i=0; i< num; i++) {
@@ -1495,8 +1495,8 @@ static void __exit ixp_module_exit(void)
                if (ixp4xx_algos[i].registered)
                        crypto_unregister_alg(&ixp4xx_algos[i].crypto);
        }
-       release_ixp_crypto();
-       platform_device_unregister(&pseudo_dev);
+       release_ixp_crypto(&pdev->dev);
+       platform_device_unregister(pdev);
 }
 
 module_init(ixp_module_init);
index 526ec77c7ba032b9af1c6772484028051a4950ef..f238cfd33847ec3c5333158ea39dac72245c8eee 100644 (file)
@@ -198,6 +198,7 @@ config TI_EDMA
        depends on ARCH_DAVINCI || ARCH_OMAP
        select DMA_ENGINE
        select DMA_VIRTUAL_CHANNELS
+       select TI_PRIV_EDMA
        default n
        help
          Enable support for the TI EDMA controller. This DMA
index fce46c5bf1c74e3d76accde7570ffa2d423eb9f1..e51a9832ef0d06801fd151b376824a7ac3d697b7 100644 (file)
@@ -2055,6 +2055,11 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
        if (ret)
                return ret;
 
+       /* Ensure that we can do DMA */
+       ret = dma_set_mask_and_coherent(&adev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               goto out_no_pl08x;
+
        /* Create the driver state holder */
        pl08x = kzalloc(sizeof(*pl08x), GFP_KERNEL);
        if (!pl08x) {
index e35d97590311329fe1f7bd93be5cc4b845f3a7c2..453822cc4f9d3a9a9c7b62626c7362c13ee8b931 100644 (file)
@@ -191,11 +191,9 @@ static int dw_probe(struct platform_device *pdev)
        if (IS_ERR(chip->regs))
                return PTR_ERR(chip->regs);
 
-       /* Apply default dma_mask if needed */
-       if (!dev->dma_mask) {
-               dev->dma_mask = &dev->coherent_dma_mask;
-               dev->coherent_dma_mask = DMA_BIT_MASK(32);
-       }
+       err = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (err)
+               return err;
 
        pdata = dev_get_platdata(dev);
        if (!pdata)
index ff50ff4c6a57148c3a015a6ba3ebb1c81f69c6f8..0ddcf16cf8cf223821d9731fe5b26318b7bad078 100644 (file)
@@ -631,6 +631,10 @@ static int edma_probe(struct platform_device *pdev)
        struct edma_cc *ecc;
        int ret;
 
+       ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
+
        ecc = devm_kzalloc(&pdev->dev, sizeof(*ecc), GFP_KERNEL);
        if (!ecc) {
                dev_err(&pdev->dev, "Can't allocate controller\n");
@@ -702,11 +706,13 @@ static struct platform_device *pdev0, *pdev1;
 static const struct platform_device_info edma_dev_info0 = {
        .name = "edma-dma-engine",
        .id = 0,
+       .dma_mask = DMA_BIT_MASK(32),
 };
 
 static const struct platform_device_info edma_dev_info1 = {
        .name = "edma-dma-engine",
        .id = 1,
+       .dma_mask = DMA_BIT_MASK(32),
 };
 
 static int edma_init(void)
@@ -720,8 +726,6 @@ static int edma_init(void)
                        ret = PTR_ERR(pdev0);
                        goto out;
                }
-               pdev0->dev.dma_mask = &pdev0->dev.coherent_dma_mask;
-               pdev0->dev.coherent_dma_mask = DMA_BIT_MASK(32);
        }
 
        if (EDMA_CTLRS == 2) {
@@ -731,8 +735,6 @@ static int edma_init(void)
                        platform_device_unregister(pdev0);
                        ret = PTR_ERR(pdev1);
                }
-               pdev1->dev.dma_mask = &pdev1->dev.coherent_dma_mask;
-               pdev1->dev.coherent_dma_mask = DMA_BIT_MASK(32);
        }
 
 out:
@@ -749,6 +751,6 @@ static void __exit edma_exit(void)
 }
 module_exit(edma_exit);
 
-MODULE_AUTHOR("Matt Porter <mporter@ti.com>");
+MODULE_AUTHOR("Matt Porter <matt.porter@linaro.org>");
 MODULE_DESCRIPTION("TI EDMA DMA engine driver");
 MODULE_LICENSE("GPL v2");
index 78f8ca5fccee91e7a422c419df4ee0ab427d4ad4..55852c02679143f453286f189e68fd777ea1afaa 100644 (file)
@@ -437,17 +437,18 @@ static void dma_irq_handle_channel(struct imxdma_channel *imxdmac)
        struct imxdma_engine *imxdma = imxdmac->imxdma;
        int chno = imxdmac->channel;
        struct imxdma_desc *desc;
+       unsigned long flags;
 
-       spin_lock(&imxdma->lock);
+       spin_lock_irqsave(&imxdma->lock, flags);
        if (list_empty(&imxdmac->ld_active)) {
-               spin_unlock(&imxdma->lock);
+               spin_unlock_irqrestore(&imxdma->lock, flags);
                goto out;
        }
 
        desc = list_first_entry(&imxdmac->ld_active,
                                struct imxdma_desc,
                                node);
-       spin_unlock(&imxdma->lock);
+       spin_unlock_irqrestore(&imxdma->lock, flags);
 
        if (desc->sg) {
                u32 tmp;
@@ -519,7 +520,6 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)
 {
        struct imxdma_channel *imxdmac = to_imxdma_chan(d->desc.chan);
        struct imxdma_engine *imxdma = imxdmac->imxdma;
-       unsigned long flags;
        int slot = -1;
        int i;
 
@@ -527,7 +527,6 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)
        switch (d->type) {
        case IMXDMA_DESC_INTERLEAVED:
                /* Try to get a free 2D slot */
-               spin_lock_irqsave(&imxdma->lock, flags);
                for (i = 0; i < IMX_DMA_2D_SLOTS; i++) {
                        if ((imxdma->slots_2d[i].count > 0) &&
                        ((imxdma->slots_2d[i].xsr != d->x) ||
@@ -537,10 +536,8 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)
                        slot = i;
                        break;
                }
-               if (slot < 0) {
-                       spin_unlock_irqrestore(&imxdma->lock, flags);
+               if (slot < 0)
                        return -EBUSY;
-               }
 
                imxdma->slots_2d[slot].xsr = d->x;
                imxdma->slots_2d[slot].ysr = d->y;
@@ -549,7 +546,6 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)
 
                imxdmac->slot_2d = slot;
                imxdmac->enabled_2d = true;
-               spin_unlock_irqrestore(&imxdma->lock, flags);
 
                if (slot == IMX_DMA_2D_SLOT_A) {
                        d->config_mem &= ~CCR_MSEL_B;
@@ -625,18 +621,17 @@ static void imxdma_tasklet(unsigned long data)
        struct imxdma_channel *imxdmac = (void *)data;
        struct imxdma_engine *imxdma = imxdmac->imxdma;
        struct imxdma_desc *desc;
+       unsigned long flags;
 
-       spin_lock(&imxdma->lock);
+       spin_lock_irqsave(&imxdma->lock, flags);
 
        if (list_empty(&imxdmac->ld_active)) {
                /* Someone might have called terminate all */
-               goto out;
+               spin_unlock_irqrestore(&imxdma->lock, flags);
+               return;
        }
        desc = list_first_entry(&imxdmac->ld_active, struct imxdma_desc, node);
 
-       if (desc->desc.callback)
-               desc->desc.callback(desc->desc.callback_param);
-
        /* If we are dealing with a cyclic descriptor, keep it on ld_active
         * and dont mark the descriptor as complete.
         * Only in non-cyclic cases it would be marked as complete
@@ -663,7 +658,11 @@ static void imxdma_tasklet(unsigned long data)
                                 __func__, imxdmac->channel);
        }
 out:
-       spin_unlock(&imxdma->lock);
+       spin_unlock_irqrestore(&imxdma->lock, flags);
+
+       if (desc->desc.callback)
+               desc->desc.callback(desc->desc.callback_param);
+
 }
 
 static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
@@ -883,7 +882,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic(
        kfree(imxdmac->sg_list);
 
        imxdmac->sg_list = kcalloc(periods + 1,
-                       sizeof(struct scatterlist), GFP_KERNEL);
+                       sizeof(struct scatterlist), GFP_ATOMIC);
        if (!imxdmac->sg_list)
                return NULL;
 
index fc43603cf0bbeca883aa260d880c86898b49e793..c1fd504cae282491969886b0d0336784229e422d 100644 (file)
@@ -1432,6 +1432,10 @@ static int __init sdma_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
+       ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
+
        sdma = kzalloc(sizeof(*sdma), GFP_KERNEL);
        if (!sdma)
                return -ENOMEM;
index a562d24d20bf55179436d16086ca90f63d1b1894..df8b10fd1726ed466d2b05e814a8feb6c711dfe3 100644 (file)
@@ -2903,6 +2903,10 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 
        pdat = dev_get_platdata(&adev->dev);
 
+       ret = dma_set_mask_and_coherent(&adev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
+
        /* Allocate a new DMAC and its Channels */
        pdmac = devm_kzalloc(&adev->dev, sizeof(*pdmac), GFP_KERNEL);
        if (!pdmac) {
index ff080ee201973bd3c76513d11d36273d70971e59..1b5e8e46226d5f3d6bebdb770d8b29de9f04fc43 100644 (file)
@@ -545,12 +545,15 @@ static int dcdbas_probe(struct platform_device *dev)
        host_control_action = HC_ACTION_NONE;
        host_control_smi_type = HC_SMITYPE_NONE;
 
+       dcdbas_pdev = dev;
+
        /*
         * BIOS SMI calls require buffer addresses be in 32-bit address space.
         * This is done by setting the DMA mask below.
         */
-       dcdbas_pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-       dcdbas_pdev->dev.dma_mask = &dcdbas_pdev->dev.coherent_dma_mask;
+       error = dma_set_coherent_mask(&dcdbas_pdev->dev, DMA_BIT_MASK(32));
+       if (error)
+               return error;
 
        error = sysfs_create_group(&dev->dev.kobj, &dcdbas_attr_group);
        if (error)
@@ -581,6 +584,14 @@ static struct platform_driver dcdbas_driver = {
        .remove         = dcdbas_remove,
 };
 
+static const struct platform_device_info dcdbas_dev_info __initdata = {
+       .name           = DRIVER_NAME,
+       .id             = -1,
+       .dma_mask       = DMA_BIT_MASK(32),
+};
+
+static struct platform_device *dcdbas_pdev_reg;
+
 /**
  * dcdbas_init: initialize driver
  */
@@ -592,20 +603,14 @@ static int __init dcdbas_init(void)
        if (error)
                return error;
 
-       dcdbas_pdev = platform_device_alloc(DRIVER_NAME, -1);
-       if (!dcdbas_pdev) {
-               error = -ENOMEM;
+       dcdbas_pdev_reg = platform_device_register_full(&dcdbas_dev_info);
+       if (IS_ERR(dcdbas_pdev_reg)) {
+               error = PTR_ERR(dcdbas_pdev_reg);
                goto err_unregister_driver;
        }
 
-       error = platform_device_add(dcdbas_pdev);
-       if (error)
-               goto err_free_device;
-
        return 0;
 
- err_free_device:
-       platform_device_put(dcdbas_pdev);
  err_unregister_driver:
        platform_driver_unregister(&dcdbas_driver);
        return error;
@@ -628,8 +633,9 @@ static void __exit dcdbas_exit(void)
         * all sysfs attributes belonging to this module have been
         * released.
         */
-       smi_data_buf_free();
-       platform_device_unregister(dcdbas_pdev);
+       if (dcdbas_pdev)
+               smi_data_buf_free();
+       platform_device_unregister(dcdbas_pdev_reg);
        platform_driver_unregister(&dcdbas_driver);
 }
 
index 6eb535ffeddc2ea7787f648d1d35734f24c305d5..e5a67b24587ac0efe1848dc08a6b465ef744f553 100644 (file)
@@ -764,6 +764,13 @@ static __init int gsmi_system_valid(void)
 static struct kobject *gsmi_kobj;
 static struct efivars efivars;
 
+static const struct platform_device_info gsmi_dev_info = {
+       .name           = "gsmi",
+       .id             = -1,
+       /* SMI callbacks require 32bit addresses */
+       .dma_mask       = DMA_BIT_MASK(32),
+};
+
 static __init int gsmi_init(void)
 {
        unsigned long flags;
@@ -776,7 +783,7 @@ static __init int gsmi_init(void)
        gsmi_dev.smi_cmd = acpi_gbl_FADT.smi_command;
 
        /* register device */
-       gsmi_dev.pdev = platform_device_register_simple("gsmi", -1, NULL, 0);
+       gsmi_dev.pdev = platform_device_register_full(&gsmi_dev_info);
        if (IS_ERR(gsmi_dev.pdev)) {
                printk(KERN_ERR "gsmi: unable to register platform device\n");
                return PTR_ERR(gsmi_dev.pdev);
@@ -785,10 +792,6 @@ static __init int gsmi_init(void)
        /* SMI access needs to be serialized */
        spin_lock_init(&gsmi_dev.lock);
 
-       /* SMI callbacks require 32bit addresses */
-       gsmi_dev.pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-       gsmi_dev.pdev->dev.dma_mask =
-               &gsmi_dev.pdev->dev.coherent_dma_mask;
        ret = -ENOMEM;
        gsmi_dev.dma_pool = dma_pool_create("gsmi", &gsmi_dev.pdev->dev,
                                             GSMI_BUF_SIZE, GSMI_BUF_ALIGN, 0);
index 0ff43552d472bf09d5ab0206437e62ae0392c6f1..89675f862308f95d41d962c3faae99b80a458869 100644 (file)
@@ -63,6 +63,7 @@ struct gpio_bank {
        struct gpio_chip chip;
        struct clk *dbck;
        u32 mod_usage;
+       u32 irq_usage;
        u32 dbck_enable_mask;
        bool dbck_enabled;
        struct device *dev;
@@ -86,6 +87,9 @@ struct gpio_bank {
 #define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio))
 #define GPIO_MOD_CTRL_BIT      BIT(0)
 
+#define BANK_USED(bank) (bank->mod_usage || bank->irq_usage)
+#define LINE_USED(line, offset) (line & (1 << offset))
+
 static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq)
 {
        return bank->chip.base + gpio_irq;
@@ -420,15 +424,69 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,
        return 0;
 }
 
+static void _enable_gpio_module(struct gpio_bank *bank, unsigned offset)
+{
+       if (bank->regs->pinctrl) {
+               void __iomem *reg = bank->base + bank->regs->pinctrl;
+
+               /* Claim the pin for MPU */
+               __raw_writel(__raw_readl(reg) | (1 << offset), reg);
+       }
+
+       if (bank->regs->ctrl && !BANK_USED(bank)) {
+               void __iomem *reg = bank->base + bank->regs->ctrl;
+               u32 ctrl;
+
+               ctrl = __raw_readl(reg);
+               /* Module is enabled, clocks are not gated */
+               ctrl &= ~GPIO_MOD_CTRL_BIT;
+               __raw_writel(ctrl, reg);
+               bank->context.ctrl = ctrl;
+       }
+}
+
+static void _disable_gpio_module(struct gpio_bank *bank, unsigned offset)
+{
+       void __iomem *base = bank->base;
+
+       if (bank->regs->wkup_en &&
+           !LINE_USED(bank->mod_usage, offset) &&
+           !LINE_USED(bank->irq_usage, offset)) {
+               /* Disable wake-up during idle for dynamic tick */
+               _gpio_rmw(base, bank->regs->wkup_en, 1 << offset, 0);
+               bank->context.wake_en =
+                       __raw_readl(bank->base + bank->regs->wkup_en);
+       }
+
+       if (bank->regs->ctrl && !BANK_USED(bank)) {
+               void __iomem *reg = bank->base + bank->regs->ctrl;
+               u32 ctrl;
+
+               ctrl = __raw_readl(reg);
+               /* Module is disabled, clocks are gated */
+               ctrl |= GPIO_MOD_CTRL_BIT;
+               __raw_writel(ctrl, reg);
+               bank->context.ctrl = ctrl;
+       }
+}
+
+static int gpio_is_input(struct gpio_bank *bank, int mask)
+{
+       void __iomem *reg = bank->base + bank->regs->direction;
+
+       return __raw_readl(reg) & mask;
+}
+
 static int gpio_irq_type(struct irq_data *d, unsigned type)
 {
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
        unsigned gpio = 0;
        int retval;
        unsigned long flags;
+       unsigned offset;
 
-       if (WARN_ON(!bank->mod_usage))
-               return -EINVAL;
+       if (!BANK_USED(bank))
+               pm_runtime_get_sync(bank->dev);
 
 #ifdef CONFIG_ARCH_OMAP1
        if (d->irq > IH_MPUIO_BASE)
@@ -446,7 +504,17 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
                return -EINVAL;
 
        spin_lock_irqsave(&bank->lock, flags);
-       retval = _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), type);
+       offset = GPIO_INDEX(bank, gpio);
+       retval = _set_gpio_triggering(bank, offset, type);
+       if (!LINE_USED(bank->mod_usage, offset)) {
+               _enable_gpio_module(bank, offset);
+               _set_gpio_direction(bank, offset, 1);
+       } else if (!gpio_is_input(bank, 1 << offset)) {
+               spin_unlock_irqrestore(&bank->lock, flags);
+               return -EINVAL;
+       }
+
+       bank->irq_usage |= 1 << GPIO_INDEX(bank, gpio);
        spin_unlock_irqrestore(&bank->lock, flags);
 
        if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
@@ -603,35 +671,19 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
         * If this is the first gpio_request for the bank,
         * enable the bank module.
         */
-       if (!bank->mod_usage)
+       if (!BANK_USED(bank))
                pm_runtime_get_sync(bank->dev);
 
        spin_lock_irqsave(&bank->lock, flags);
        /* Set trigger to none. You need to enable the desired trigger with
-        * request_irq() or set_irq_type().
+        * request_irq() or set_irq_type(). Only do this if the IRQ line has
+        * not already been requested.
         */
-       _set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
-
-       if (bank->regs->pinctrl) {
-               void __iomem *reg = bank->base + bank->regs->pinctrl;
-
-               /* Claim the pin for MPU */
-               __raw_writel(__raw_readl(reg) | (1 << offset), reg);
-       }
-
-       if (bank->regs->ctrl && !bank->mod_usage) {
-               void __iomem *reg = bank->base + bank->regs->ctrl;
-               u32 ctrl;
-
-               ctrl = __raw_readl(reg);
-               /* Module is enabled, clocks are not gated */
-               ctrl &= ~GPIO_MOD_CTRL_BIT;
-               __raw_writel(ctrl, reg);
-               bank->context.ctrl = ctrl;
+       if (!LINE_USED(bank->irq_usage, offset)) {
+               _set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
+               _enable_gpio_module(bank, offset);
        }
-
        bank->mod_usage |= 1 << offset;
-
        spin_unlock_irqrestore(&bank->lock, flags);
 
        return 0;
@@ -640,31 +692,11 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
 static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
 {
        struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
-       void __iomem *base = bank->base;
        unsigned long flags;
 
        spin_lock_irqsave(&bank->lock, flags);
-
-       if (bank->regs->wkup_en) {
-               /* Disable wake-up during idle for dynamic tick */
-               _gpio_rmw(base, bank->regs->wkup_en, 1 << offset, 0);
-               bank->context.wake_en =
-                       __raw_readl(bank->base + bank->regs->wkup_en);
-       }
-
        bank->mod_usage &= ~(1 << offset);
-
-       if (bank->regs->ctrl && !bank->mod_usage) {
-               void __iomem *reg = bank->base + bank->regs->ctrl;
-               u32 ctrl;
-
-               ctrl = __raw_readl(reg);
-               /* Module is disabled, clocks are gated */
-               ctrl |= GPIO_MOD_CTRL_BIT;
-               __raw_writel(ctrl, reg);
-               bank->context.ctrl = ctrl;
-       }
-
+       _disable_gpio_module(bank, offset);
        _reset_gpio(bank, bank->chip.base + offset);
        spin_unlock_irqrestore(&bank->lock, flags);
 
@@ -672,7 +704,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
         * If this is the last gpio to be freed in the bank,
         * disable the bank module.
         */
-       if (!bank->mod_usage)
+       if (!BANK_USED(bank))
                pm_runtime_put(bank->dev);
 }
 
@@ -762,10 +794,20 @@ static void gpio_irq_shutdown(struct irq_data *d)
        struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
        unsigned int gpio = irq_to_gpio(bank, d->hwirq);
        unsigned long flags;
+       unsigned offset = GPIO_INDEX(bank, gpio);
 
        spin_lock_irqsave(&bank->lock, flags);
+       bank->irq_usage &= ~(1 << offset);
+       _disable_gpio_module(bank, offset);
        _reset_gpio(bank, gpio);
        spin_unlock_irqrestore(&bank->lock, flags);
+
+       /*
+        * If this is the last IRQ to be freed in the bank,
+        * disable the bank module.
+        */
+       if (!BANK_USED(bank))
+               pm_runtime_put(bank->dev);
 }
 
 static void gpio_ack_irq(struct irq_data *d)
@@ -897,13 +939,6 @@ static int gpio_input(struct gpio_chip *chip, unsigned offset)
        return 0;
 }
 
-static int gpio_is_input(struct gpio_bank *bank, int mask)
-{
-       void __iomem *reg = bank->base + bank->regs->direction;
-
-       return __raw_readl(reg) & mask;
-}
-
 static int gpio_get(struct gpio_chip *chip, unsigned offset)
 {
        struct gpio_bank *bank;
@@ -922,13 +957,22 @@ static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
 {
        struct gpio_bank *bank;
        unsigned long flags;
+       int retval = 0;
 
        bank = container_of(chip, struct gpio_bank, chip);
        spin_lock_irqsave(&bank->lock, flags);
+
+       if (LINE_USED(bank->irq_usage, offset)) {
+                       retval = -EINVAL;
+                       goto exit;
+       }
+
        bank->set_dataout(bank, offset, value);
        _set_gpio_direction(bank, offset, 0);
+
+exit:
        spin_unlock_irqrestore(&bank->lock, flags);
-       return 0;
+       return retval;
 }
 
 static int gpio_debounce(struct gpio_chip *chip, unsigned offset,
@@ -1400,7 +1444,7 @@ void omap2_gpio_prepare_for_idle(int pwr_mode)
        struct gpio_bank *bank;
 
        list_for_each_entry(bank, &omap_gpio_list, node) {
-               if (!bank->mod_usage || !bank->loses_context)
+               if (!BANK_USED(bank) || !bank->loses_context)
                        continue;
 
                bank->power_mode = pwr_mode;
@@ -1414,7 +1458,7 @@ void omap2_gpio_resume_after_idle(void)
        struct gpio_bank *bank;
 
        list_for_each_entry(bank, &omap_gpio_list, node) {
-               if (!bank->mod_usage || !bank->loses_context)
+               if (!BANK_USED(bank) || !bank->loses_context)
                        continue;
 
                pm_runtime_get_sync(bank->dev);
index e3745eb075708092d0a56e04f7bb2a10b4d274dd..6038966ab045529b071242424e49b12237db316a 100644 (file)
@@ -293,10 +293,9 @@ static void gpio_rcar_parse_pdata(struct gpio_rcar_priv *p)
        if (pdata) {
                p->config = *pdata;
        } else if (IS_ENABLED(CONFIG_OF) && np) {
-               ret = of_parse_phandle_with_args(np, "gpio-ranges",
-                               "#gpio-range-cells", 0, &args);
-               p->config.number_of_pins = ret == 0 && args.args_count == 3
-                                        ? args.args[2]
+               ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0,
+                                                      &args);
+               p->config.number_of_pins = ret == 0 ? args.args[2]
                                         : RCAR_MAX_GPIO_PER_BANK;
                p->config.gpio_base = -1;
        }
index 8ea3b33d4b40bb4b96ad7edd83f6dac7e219aa03..a90be34e4d5c24569dc64a320e59d0a9474e0908 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/module.h>
-
+#include <linux/io.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 
index 796dbb212a4138180f7bda2e50fb765f22805c93..8492b68e873c174cda6e99e70cf976a90e5ddaff 100644 (file)
@@ -177,7 +177,7 @@ uint8_t ast_get_index_reg_mask(struct ast_private *ast,
 
 static inline void ast_open_key(struct ast_private *ast)
 {
-       ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xA1, 0xFF, 0x04);
+       ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x80, 0xA8);
 }
 
 #define AST_VIDMEM_SIZE_8M    0x00800000
index b4fb86d89850a31c3cc9424f4b4148831c59922f..224ff965bcf7de624c3b62b6db153bda090ea4a9 100644 (file)
 
 #include <drm/drmP.h>
 
+/******************************************************************/
+/** \name Context bitmap support */
+/*@{*/
+
 /**
  * Free a handle from the context bitmap.
  *
  * in drm_device::ctx_idr, while holding the drm_device::struct_mutex
  * lock.
  */
-static void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
+void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
 {
-       if (drm_core_check_feature(dev, DRIVER_MODESET))
-               return;
-
        mutex_lock(&dev->struct_mutex);
        idr_remove(&dev->ctx_idr, ctx_handle);
        mutex_unlock(&dev->struct_mutex);
 }
 
-/******************************************************************/
-/** \name Context bitmap support */
-/*@{*/
-
-void drm_legacy_ctxbitmap_release(struct drm_device *dev,
-                                 struct drm_file *file_priv)
-{
-       if (drm_core_check_feature(dev, DRIVER_MODESET))
-               return;
-
-       mutex_lock(&dev->ctxlist_mutex);
-       if (!list_empty(&dev->ctxlist)) {
-               struct drm_ctx_list *pos, *n;
-
-               list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
-                       if (pos->tag == file_priv &&
-                           pos->handle != DRM_KERNEL_CONTEXT) {
-                               if (dev->driver->context_dtor)
-                                       dev->driver->context_dtor(dev,
-                                                                 pos->handle);
-
-                               drm_ctxbitmap_free(dev, pos->handle);
-
-                               list_del(&pos->head);
-                               kfree(pos);
-                               --dev->ctx_count;
-                       }
-               }
-       }
-       mutex_unlock(&dev->ctxlist_mutex);
-}
-
 /**
  * Context bitmap allocation.
  *
@@ -121,12 +90,10 @@ static int drm_ctxbitmap_next(struct drm_device * dev)
  *
  * Initialise the drm_device::ctx_idr
  */
-void drm_legacy_ctxbitmap_init(struct drm_device * dev)
+int drm_ctxbitmap_init(struct drm_device * dev)
 {
-       if (drm_core_check_feature(dev, DRIVER_MODESET))
-               return;
-
        idr_init(&dev->ctx_idr);
+       return 0;
 }
 
 /**
@@ -137,7 +104,7 @@ void drm_legacy_ctxbitmap_init(struct drm_device * dev)
  * Free all idr members using drm_ctx_sarea_free helper function
  * while holding the drm_device::struct_mutex lock.
  */
-void drm_legacy_ctxbitmap_cleanup(struct drm_device * dev)
+void drm_ctxbitmap_cleanup(struct drm_device * dev)
 {
        mutex_lock(&dev->struct_mutex);
        idr_destroy(&dev->ctx_idr);
@@ -169,9 +136,6 @@ int drm_getsareactx(struct drm_device *dev, void *data,
        struct drm_local_map *map;
        struct drm_map_list *_entry;
 
-       if (drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        mutex_lock(&dev->struct_mutex);
 
        map = idr_find(&dev->ctx_idr, request->ctx_id);
@@ -216,9 +180,6 @@ int drm_setsareactx(struct drm_device *dev, void *data,
        struct drm_local_map *map = NULL;
        struct drm_map_list *r_list = NULL;
 
-       if (drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        mutex_lock(&dev->struct_mutex);
        list_for_each_entry(r_list, &dev->maplist, head) {
                if (r_list->map
@@ -319,9 +280,6 @@ int drm_resctx(struct drm_device *dev, void *data,
        struct drm_ctx ctx;
        int i;
 
-       if (drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        if (res->count >= DRM_RESERVED_CONTEXTS) {
                memset(&ctx, 0, sizeof(ctx));
                for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
@@ -352,9 +310,6 @@ int drm_addctx(struct drm_device *dev, void *data,
        struct drm_ctx_list *ctx_entry;
        struct drm_ctx *ctx = data;
 
-       if (drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        ctx->handle = drm_ctxbitmap_next(dev);
        if (ctx->handle == DRM_KERNEL_CONTEXT) {
                /* Skip kernel's context and get a new one. */
@@ -398,9 +353,6 @@ int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
        struct drm_ctx *ctx = data;
 
-       if (drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        /* This is 0, because we don't handle any context flags */
        ctx->flags = 0;
 
@@ -423,9 +375,6 @@ int drm_switchctx(struct drm_device *dev, void *data,
 {
        struct drm_ctx *ctx = data;
 
-       if (drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        DRM_DEBUG("%d\n", ctx->handle);
        return drm_context_switch(dev, dev->last_context, ctx->handle);
 }
@@ -446,9 +395,6 @@ int drm_newctx(struct drm_device *dev, void *data,
 {
        struct drm_ctx *ctx = data;
 
-       if (drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        DRM_DEBUG("%d\n", ctx->handle);
        drm_context_switch_complete(dev, file_priv, ctx->handle);
 
@@ -471,9 +417,6 @@ int drm_rmctx(struct drm_device *dev, void *data,
 {
        struct drm_ctx *ctx = data;
 
-       if (drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
        DRM_DEBUG("%d\n", ctx->handle);
        if (ctx->handle != DRM_KERNEL_CONTEXT) {
                if (dev->driver->context_dtor)
index 3d13ca6e257f0f2c6bd366a49f8b7f3622e592dd..f6f6cc7fc133292e9fe3375502466b0abd1b0fa9 100644 (file)
@@ -407,6 +407,14 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
        struct drm_connector *connector;
        int i, j;
 
+       /*
+        * fbdev->blank can be called from irq context in case of a panic.
+        * Since we already have our own special panic handler which will
+        * restore the fbdev console mode completely, just bail out early.
+        */
+       if (oops_in_progress)
+               return;
+
        /*
         * fbdev->blank can be called from irq context in case of a panic.
         * Since we already have our own special panic handler which will
index 4be8e09a32ef730db4740f6f69e52f91ca829112..3f84277d7036b3f843120fb4145dc081010d3d0d 100644 (file)
@@ -439,7 +439,26 @@ int drm_release(struct inode *inode, struct file *filp)
        if (dev->driver->driver_features & DRIVER_GEM)
                drm_gem_release(dev, file_priv);
 
-       drm_legacy_ctxbitmap_release(dev, file_priv);
+       mutex_lock(&dev->ctxlist_mutex);
+       if (!list_empty(&dev->ctxlist)) {
+               struct drm_ctx_list *pos, *n;
+
+               list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
+                       if (pos->tag == file_priv &&
+                           pos->handle != DRM_KERNEL_CONTEXT) {
+                               if (dev->driver->context_dtor)
+                                       dev->driver->context_dtor(dev,
+                                                                 pos->handle);
+
+                               drm_ctxbitmap_free(dev, pos->handle);
+
+                               list_del(&pos->head);
+                               kfree(pos);
+                               --dev->ctx_count;
+                       }
+               }
+       }
+       mutex_unlock(&dev->ctxlist_mutex);
 
        mutex_lock(&dev->struct_mutex);
 
index e7eb0276f7f1968e6c71997eab517fd3a6746fac..39d864576be4a4d5f5957cdbf1e3112b1322a018 100644 (file)
@@ -292,7 +292,13 @@ int drm_fill_in_dev(struct drm_device *dev,
                        goto error_out_unreg;
        }
 
-       drm_legacy_ctxbitmap_init(dev);
+
+
+       retcode = drm_ctxbitmap_init(dev);
+       if (retcode) {
+               DRM_ERROR("Cannot allocate memory for context bitmap.\n");
+               goto error_out_unreg;
+       }
 
        if (driver->driver_features & DRIVER_GEM) {
                retcode = drm_gem_init(dev);
@@ -446,7 +452,7 @@ void drm_put_dev(struct drm_device *dev)
                drm_rmmap(dev, r_list->map);
        drm_ht_remove(&dev->map_hash);
 
-       drm_legacy_ctxbitmap_cleanup(dev);
+       drm_ctxbitmap_cleanup(dev);
 
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                drm_put_minor(&dev->control);
index 4752f223e5b28a2fb793eb5b83be0fefb89a7ac2..45b6ef595965b7cb7391125d8b3a4caf2703b2b5 100644 (file)
@@ -56,7 +56,7 @@ config DRM_EXYNOS_IPP
 
 config DRM_EXYNOS_FIMC
        bool "Exynos DRM FIMC"
-       depends on DRM_EXYNOS_IPP && MFD_SYSCON && OF
+       depends on DRM_EXYNOS_IPP && MFD_SYSCON
        help
          Choose this option if you want to use Exynos FIMC for DRM.
 
index 3445a0f3a6b29dc6110d0e3a950a23de92a4098c..9c8088462c26f970d42b2fb40dae86490e51d3f6 100644 (file)
@@ -63,7 +63,8 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
                        return -ENOMEM;
                }
 
-               buf->kvaddr = dma_alloc_attrs(dev->dev, buf->size,
+               buf->kvaddr = (void __iomem *)dma_alloc_attrs(dev->dev,
+                                       buf->size,
                                        &buf->dma_addr, GFP_KERNEL,
                                        &buf->dma_attrs);
                if (!buf->kvaddr) {
@@ -90,9 +91,9 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
        }
 
        buf->sgt = drm_prime_pages_to_sg(buf->pages, nr_pages);
-       if (!buf->sgt) {
+       if (IS_ERR(buf->sgt)) {
                DRM_ERROR("failed to get sg table.\n");
-               ret = -ENOMEM;
+               ret = PTR_ERR(buf->sgt);
                goto err_free_attrs;
        }
 
index bb82ef78ca851101458a76178656a6f5646137b1..81192d00b39ec55f72afc68aa3ce0aab448a3e5d 100644 (file)
@@ -286,7 +286,11 @@ static struct drm_driver exynos_drm_driver = {
 
 static int exynos_drm_platform_probe(struct platform_device *pdev)
 {
-       pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       int ret;
+
+       ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        return drm_platform_init(&exynos_drm_driver, pdev);
 }
index 78e868bcf1ecc364638e4ce3343cc66f260599f0..e7c2f2d07f193b0393052be2e1bf32921b804da9 100644 (file)
@@ -99,12 +99,13 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
                if (is_drm_iommu_supported(dev)) {
                        unsigned int nr_pages = buffer->size >> PAGE_SHIFT;
 
-                       buffer->kvaddr = vmap(buffer->pages, nr_pages, VM_MAP,
+                       buffer->kvaddr = (void __iomem *) vmap(buffer->pages,
+                                       nr_pages, VM_MAP,
                                        pgprot_writecombine(PAGE_KERNEL));
                } else {
                        phys_addr_t dma_addr = buffer->dma_addr;
                        if (dma_addr)
-                               buffer->kvaddr = phys_to_virt(dma_addr);
+                               buffer->kvaddr = (void __iomem *)phys_to_virt(dma_addr);
                        else
                                buffer->kvaddr = (void __iomem *)NULL;
                }
index b1f8fc69023fd97f9ee2ac28b3aaf35760aa3323..60e84043aa348fe3ec4293507edeb6b9477e3dc2 100644 (file)
@@ -707,8 +707,7 @@ tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
                reg_write(encoder, REG_VIP_CNTRL_2, priv->vip_cntrl_2);
                break;
        case DRM_MODE_DPMS_OFF:
-               /* disable audio and video ports */
-               reg_write(encoder, REG_ENA_AP, 0x00);
+               /* disable video ports */
                reg_write(encoder, REG_ENA_VP_0, 0x00);
                reg_write(encoder, REG_ENA_VP_1, 0x00);
                reg_write(encoder, REG_ENA_VP_2, 0x00);
index 8507c6d1e642d872c48f41834a5dbeca53d99c6b..cdfb9da0e4ce944529a329ce29f92d391e19973a 100644 (file)
@@ -1392,14 +1392,11 @@ out:
                if (i915_terminally_wedged(&dev_priv->gpu_error))
                        return VM_FAULT_SIGBUS;
        case -EAGAIN:
-               /* Give the error handler a chance to run and move the
-                * objects off the GPU active list. Next time we service the
-                * fault, we should be able to transition the page into the
-                * GTT without touching the GPU (and so avoid further
-                * EIO/EGAIN). If the GPU is wedged, then there is no issue
-                * with coherency, just lost writes.
+               /*
+                * EAGAIN means the gpu is hung and we'll wait for the error
+                * handler to reset everything when re-faulting in
+                * i915_mutex_lock_interruptible.
                 */
-               set_need_resched();
        case 0:
        case -ERESTARTSYS:
        case -EINTR:
@@ -4803,10 +4800,10 @@ i915_gem_inactive_count(struct shrinker *shrinker, struct shrink_control *sc)
 
        if (!mutex_trylock(&dev->struct_mutex)) {
                if (!mutex_is_locked_by(&dev->struct_mutex, current))
-                       return SHRINK_STOP;
+                       return 0;
 
                if (dev_priv->mm.shrinker_no_lock_stealing)
-                       return SHRINK_STOP;
+                       return 0;
 
                unlock = false;
        }
@@ -4904,10 +4901,10 @@ i915_gem_inactive_scan(struct shrinker *shrinker, struct shrink_control *sc)
 
        if (!mutex_trylock(&dev->struct_mutex)) {
                if (!mutex_is_locked_by(&dev->struct_mutex, current))
-                       return 0;
+                       return SHRINK_STOP;
 
                if (dev_priv->mm.shrinker_no_lock_stealing)
-                       return 0;
+                       return SHRINK_STOP;
 
                unlock = false;
        }
index aba9d7498996c29845e6691ac4eff83c8fe85223..dae364f0028cc94d58f87613449b41d7620d7f29 100644 (file)
@@ -143,8 +143,10 @@ static void i915_error_vprintf(struct drm_i915_error_state_buf *e,
 
        /* Seek the first printf which is hits start position */
        if (e->pos < e->start) {
-               len = vsnprintf(NULL, 0, f, args);
-               if (!__i915_error_seek(e, len))
+               va_list tmp;
+
+               va_copy(tmp, args);
+               if (!__i915_error_seek(e, vsnprintf(NULL, 0, f, tmp)))
                        return;
        }
 
index 83cce0cdb7691a9aa6024defc01c869a57b4a90a..4b91228fd9bd8e50e1319816a9fe53b6f166ec68 100644 (file)
@@ -1469,6 +1469,34 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
        return ret;
 }
 
+static void i915_error_wake_up(struct drm_i915_private *dev_priv,
+                              bool reset_completed)
+{
+       struct intel_ring_buffer *ring;
+       int i;
+
+       /*
+        * Notify all waiters for GPU completion events that reset state has
+        * been changed, and that they need to restart their wait after
+        * checking for potential errors (and bail out to drop locks if there is
+        * a gpu reset pending so that i915_error_work_func can acquire them).
+        */
+
+       /* Wake up __wait_seqno, potentially holding dev->struct_mutex. */
+       for_each_ring(ring, dev_priv, i)
+               wake_up_all(&ring->irq_queue);
+
+       /* Wake up intel_crtc_wait_for_pending_flips, holding crtc->mutex. */
+       wake_up_all(&dev_priv->pending_flip_queue);
+
+       /*
+        * Signal tasks blocked in i915_gem_wait_for_error that the pending
+        * reset state is cleared.
+        */
+       if (reset_completed)
+               wake_up_all(&dev_priv->gpu_error.reset_queue);
+}
+
 /**
  * i915_error_work_func - do process context error handling work
  * @work: work struct
@@ -1483,11 +1511,10 @@ static void i915_error_work_func(struct work_struct *work)
        drm_i915_private_t *dev_priv = container_of(error, drm_i915_private_t,
                                                    gpu_error);
        struct drm_device *dev = dev_priv->dev;
-       struct intel_ring_buffer *ring;
        char *error_event[] = { I915_ERROR_UEVENT "=1", NULL };
        char *reset_event[] = { I915_RESET_UEVENT "=1", NULL };
        char *reset_done_event[] = { I915_ERROR_UEVENT "=0", NULL };
-       int i, ret;
+       int ret;
 
        kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event);
 
@@ -1506,8 +1533,16 @@ static void i915_error_work_func(struct work_struct *work)
                kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE,
                                   reset_event);
 
+               /*
+                * All state reset _must_ be completed before we update the
+                * reset counter, for otherwise waiters might miss the reset
+                * pending state and not properly drop locks, resulting in
+                * deadlocks with the reset work.
+                */
                ret = i915_reset(dev);
 
+               intel_display_handle_reset(dev);
+
                if (ret == 0) {
                        /*
                         * After all the gem state is reset, increment the reset
@@ -1528,12 +1563,11 @@ static void i915_error_work_func(struct work_struct *work)
                        atomic_set(&error->reset_counter, I915_WEDGED);
                }
 
-               for_each_ring(ring, dev_priv, i)
-                       wake_up_all(&ring->irq_queue);
-
-               intel_display_handle_reset(dev);
-
-               wake_up_all(&dev_priv->gpu_error.reset_queue);
+               /*
+                * Note: The wake_up also serves as a memory barrier so that
+                * waiters see the update value of the reset counter atomic_t.
+                */
+               i915_error_wake_up(dev_priv, true);
        }
 }
 
@@ -1642,8 +1676,6 @@ static void i915_report_and_clear_eir(struct drm_device *dev)
 void i915_handle_error(struct drm_device *dev, bool wedged)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_ring_buffer *ring;
-       int i;
 
        i915_capture_error_state(dev);
        i915_report_and_clear_eir(dev);
@@ -1653,11 +1685,19 @@ void i915_handle_error(struct drm_device *dev, bool wedged)
                                &dev_priv->gpu_error.reset_counter);
 
                /*
-                * Wakeup waiting processes so that the reset work item
-                * doesn't deadlock trying to grab various locks.
+                * Wakeup waiting processes so that the reset work function
+                * i915_error_work_func doesn't deadlock trying to grab various
+                * locks. By bumping the reset counter first, the woken
+                * processes will see a reset in progress and back off,
+                * releasing their locks and then wait for the reset completion.
+                * We must do this for _all_ gpu waiters that might hold locks
+                * that the reset work needs to acquire.
+                *
+                * Note: The wake_up serves as the required memory barrier to
+                * ensure that the waiters see the updated value of the reset
+                * counter atomic_t.
                 */
-               for_each_ring(ring, dev_priv, i)
-                       wake_up_all(&ring->irq_queue);
+               i915_error_wake_up(dev_priv, false);
        }
 
        /*
index 63aca49d11a843a6ad6ae1a62dc11d0b3bfd470c..63de2701b97403a82ffd221424d5b5b9acda5843 100644 (file)
@@ -778,7 +778,7 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
                        /* Can only use the always-on power well for eDP when
                         * not using the panel fitter, and when not using motion
                          * blur mitigation (which we don't support). */
-                       if (intel_crtc->config.pch_pfit.size)
+                       if (intel_crtc->config.pch_pfit.enabled)
                                temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
                        else
                                temp |= TRANS_DDI_EDP_INPUT_A_ON;
index 2489d0b4c7d2db8a8b5d74c04107f1b405c8ad35..e5822e79f912d9d447901f7dbf71fe911b5ade30 100644 (file)
@@ -2249,7 +2249,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                I915_WRITE(PIPESRC(intel_crtc->pipe),
                           ((crtc->mode.hdisplay - 1) << 16) |
                           (crtc->mode.vdisplay - 1));
-               if (!intel_crtc->config.pch_pfit.size &&
+               if (!intel_crtc->config.pch_pfit.enabled &&
                    (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) ||
                     intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
                        I915_WRITE(PF_CTL(intel_crtc->pipe), 0);
@@ -3203,7 +3203,7 @@ static void ironlake_pfit_enable(struct intel_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe = crtc->pipe;
 
-       if (crtc->config.pch_pfit.size) {
+       if (crtc->config.pch_pfit.enabled) {
                /* Force use of hard-coded filter coefficients
                 * as some pre-programmed values are broken,
                 * e.g. x201.
@@ -3428,7 +3428,7 @@ static void ironlake_pfit_disable(struct intel_crtc *crtc)
 
        /* To avoid upsetting the power well on haswell only disable the pfit if
         * it's in use. The hw state code will make sure we get this right. */
-       if (crtc->config.pch_pfit.size) {
+       if (crtc->config.pch_pfit.enabled) {
                I915_WRITE(PF_CTL(pipe), 0);
                I915_WRITE(PF_WIN_POS(pipe), 0);
                I915_WRITE(PF_WIN_SZ(pipe), 0);
@@ -4775,6 +4775,10 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
 
        pipeconf = 0;
 
+       if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&
+           I915_READ(PIPECONF(intel_crtc->pipe)) & PIPECONF_ENABLE)
+               pipeconf |= PIPECONF_ENABLE;
+
        if (intel_crtc->pipe == 0 && INTEL_INFO(dev)->gen < 4) {
                /* Enable pixel doubling when the dot clock is > 90% of the (display)
                 * core speed.
@@ -4877,9 +4881,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
                return -EINVAL;
        }
 
-       /* Ensure that the cursor is valid for the new mode before changing... */
-       intel_crtc_update_cursor(crtc, true);
-
        if (is_lvds && dev_priv->lvds_downclock_avail) {
                /*
                 * Ensure we match the reduced clock's P to the target clock.
@@ -5768,9 +5769,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
                intel_crtc->config.dpll.p2 = clock.p2;
        }
 
-       /* Ensure that the cursor is valid for the new mode before changing... */
-       intel_crtc_update_cursor(crtc, true);
-
        /* CPU eDP is the only output that doesn't need a PCH PLL of its own. */
        if (intel_crtc->config.has_pch_encoder) {
                fp = i9xx_dpll_compute_fp(&intel_crtc->config.dpll);
@@ -5859,6 +5857,7 @@ static void ironlake_get_pfit_config(struct intel_crtc *crtc,
        tmp = I915_READ(PF_CTL(crtc->pipe));
 
        if (tmp & PF_ENABLE) {
+               pipe_config->pch_pfit.enabled = true;
                pipe_config->pch_pfit.pos = I915_READ(PF_WIN_POS(crtc->pipe));
                pipe_config->pch_pfit.size = I915_READ(PF_WIN_SZ(crtc->pipe));
 
@@ -6236,7 +6235,7 @@ static void haswell_modeset_global_resources(struct drm_device *dev)
                if (!crtc->base.enabled)
                        continue;
 
-               if (crtc->pipe != PIPE_A || crtc->config.pch_pfit.size ||
+               if (crtc->pipe != PIPE_A || crtc->config.pch_pfit.enabled ||
                    crtc->config.cpu_transcoder != TRANSCODER_EDP)
                        enable = true;
        }
@@ -6259,9 +6258,6 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
        if (!intel_ddi_pll_mode_set(crtc))
                return -EINVAL;
 
-       /* Ensure that the cursor is valid for the new mode before changing... */
-       intel_crtc_update_cursor(crtc, true);
-
        if (intel_crtc->config.has_dp_encoder)
                intel_dp_set_m_n(intel_crtc);
 
@@ -6494,15 +6490,15 @@ static void haswell_write_eld(struct drm_connector *connector,
 
        /* Set ELD valid state */
        tmp = I915_READ(aud_cntrl_st2);
-       DRM_DEBUG_DRIVER("HDMI audio: pin eld vld status=0x%8x\n", tmp);
+       DRM_DEBUG_DRIVER("HDMI audio: pin eld vld status=0x%08x\n", tmp);
        tmp |= (AUDIO_ELD_VALID_A << (pipe * 4));
        I915_WRITE(aud_cntrl_st2, tmp);
        tmp = I915_READ(aud_cntrl_st2);
-       DRM_DEBUG_DRIVER("HDMI audio: eld vld status=0x%8x\n", tmp);
+       DRM_DEBUG_DRIVER("HDMI audio: eld vld status=0x%08x\n", tmp);
 
        /* Enable HDMI mode */
        tmp = I915_READ(aud_config);
-       DRM_DEBUG_DRIVER("HDMI audio: audio conf: 0x%8x\n", tmp);
+       DRM_DEBUG_DRIVER("HDMI audio: audio conf: 0x%08x\n", tmp);
        /* clear N_programing_enable and N_value_index */
        tmp &= ~(AUD_CONFIG_N_VALUE_INDEX | AUD_CONFIG_N_PROG_ENABLE);
        I915_WRITE(aud_config, tmp);
@@ -6937,7 +6933,8 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
        intel_crtc->cursor_width = width;
        intel_crtc->cursor_height = height;
 
-       intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL);
+       if (intel_crtc->active)
+               intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL);
 
        return 0;
 fail_unpin:
@@ -6956,7 +6953,8 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
        intel_crtc->cursor_x = x;
        intel_crtc->cursor_y = y;
 
-       intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL);
+       if (intel_crtc->active)
+               intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL);
 
        return 0;
 }
@@ -8205,9 +8203,10 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
                      pipe_config->gmch_pfit.control,
                      pipe_config->gmch_pfit.pgm_ratios,
                      pipe_config->gmch_pfit.lvds_border_bits);
-       DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x\n",
+       DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x, %s\n",
                      pipe_config->pch_pfit.pos,
-                     pipe_config->pch_pfit.size);
+                     pipe_config->pch_pfit.size,
+                     pipe_config->pch_pfit.enabled ? "enabled" : "disabled");
        DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled);
 }
 
@@ -8603,8 +8602,11 @@ intel_pipe_config_compare(struct drm_device *dev,
        if (INTEL_INFO(dev)->gen < 4)
                PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios);
        PIPE_CONF_CHECK_I(gmch_pfit.lvds_border_bits);
-       PIPE_CONF_CHECK_I(pch_pfit.pos);
-       PIPE_CONF_CHECK_I(pch_pfit.size);
+       PIPE_CONF_CHECK_I(pch_pfit.enabled);
+       if (current_config->pch_pfit.enabled) {
+               PIPE_CONF_CHECK_I(pch_pfit.pos);
+               PIPE_CONF_CHECK_I(pch_pfit.size);
+       }
 
        PIPE_CONF_CHECK_I(ips_enabled);
 
index 2151d13772b8248cf1f6d6d71c2720fa074fe435..79c14e298ba657d32f0a57493ec9500b5216ba2d 100644 (file)
@@ -588,7 +588,18 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                        DRM_DEBUG_KMS("aux_ch native nack\n");
                        return -EREMOTEIO;
                case AUX_NATIVE_REPLY_DEFER:
-                       udelay(100);
+                       /*
+                        * For now, just give more slack to branch devices. We
+                        * could check the DPCD for I2C bit rate capabilities,
+                        * and if available, adjust the interval. We could also
+                        * be more careful with DP-to-Legacy adapters where a
+                        * long legacy cable may force very low I2C bit rates.
+                        */
+                       if (intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
+                           DP_DWN_STRM_PORT_PRESENT)
+                               usleep_range(500, 600);
+                       else
+                               usleep_range(300, 400);
                        continue;
                default:
                        DRM_ERROR("aux_ch invalid native reply 0x%02x\n",
index a47799e832c6e61f5ff02afbf35ebe2cde73a4ed..28cae80495e2b1e9d1f4fe0d089bbd63fd7a11b7 100644 (file)
@@ -280,6 +280,7 @@ struct intel_crtc_config {
        struct {
                u32 pos;
                u32 size;
+               bool enabled;
        } pch_pfit;
 
        /* FDI configuration, only valid if has_pch_encoder is set. */
index 406303b509c1c0afeed4be9379060e5417e212e0..7fa7df546c1ee6e36e119af34d6e79a9d7015e82 100644 (file)
@@ -263,6 +263,8 @@ static bool intel_dvo_compute_config(struct intel_encoder *encoder,
                C(vtotal);
                C(clock);
 #undef C
+
+               drm_mode_set_crtcinfo(adjusted_mode, 0);
        }
 
        if (intel_dvo->dev.dev_ops->mode_fixup)
index 42114ecbae0e3c4c8dc51b7b02a1f658de857873..293564a2896a19038cc87ecba7648bce511388d2 100644 (file)
@@ -112,6 +112,7 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
 done:
        pipe_config->pch_pfit.pos = (x << 16) | y;
        pipe_config->pch_pfit.size = (width << 16) | height;
+       pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0;
 }
 
 static void
index 0c115cc4899ffbe00de6ca305d5cd32bd2590405..dd176b7296c1c44904a163cfe82960f6e196249d 100644 (file)
@@ -2096,16 +2096,16 @@ static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev,
                                    struct drm_crtc *crtc)
 {
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       uint32_t pixel_rate, pfit_size;
+       uint32_t pixel_rate;
 
        pixel_rate = intel_crtc->config.adjusted_mode.clock;
 
        /* We only use IF-ID interlacing. If we ever use PF-ID we'll need to
         * adjust the pixel_rate here. */
 
-       pfit_size = intel_crtc->config.pch_pfit.size;
-       if (pfit_size) {
+       if (intel_crtc->config.pch_pfit.enabled) {
                uint64_t pipe_w, pipe_h, pfit_w, pfit_h;
+               uint32_t pfit_size = intel_crtc->config.pch_pfit.size;
 
                pipe_w = intel_crtc->config.requested_mode.hdisplay;
                pipe_h = intel_crtc->config.requested_mode.vdisplay;
index 85037b9d4934d406306634c486ed93cc92b771f3..49482fd5b76c6cad80298d2d2f67c0050c73a93d 100644 (file)
@@ -788,6 +788,8 @@ static void intel_sdvo_get_dtd_from_mode(struct intel_sdvo_dtd *dtd,
        uint16_t h_sync_offset, v_sync_offset;
        int mode_clock;
 
+       memset(dtd, 0, sizeof(*dtd));
+
        width = mode->hdisplay;
        height = mode->vdisplay;
 
@@ -830,44 +832,51 @@ static void intel_sdvo_get_dtd_from_mode(struct intel_sdvo_dtd *dtd,
        if (mode->flags & DRM_MODE_FLAG_PVSYNC)
                dtd->part2.dtd_flags |= DTD_FLAG_VSYNC_POSITIVE;
 
-       dtd->part2.sdvo_flags = 0;
        dtd->part2.v_sync_off_high = v_sync_offset & 0xc0;
-       dtd->part2.reserved = 0;
 }
 
-static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode,
+static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode *pmode,
                                         const struct intel_sdvo_dtd *dtd)
 {
-       mode->hdisplay = dtd->part1.h_active;
-       mode->hdisplay += ((dtd->part1.h_high >> 4) & 0x0f) << 8;
-       mode->hsync_start = mode->hdisplay + dtd->part2.h_sync_off;
-       mode->hsync_start += (dtd->part2.sync_off_width_high & 0xc0) << 2;
-       mode->hsync_end = mode->hsync_start + dtd->part2.h_sync_width;
-       mode->hsync_end += (dtd->part2.sync_off_width_high & 0x30) << 4;
-       mode->htotal = mode->hdisplay + dtd->part1.h_blank;
-       mode->htotal += (dtd->part1.h_high & 0xf) << 8;
-
-       mode->vdisplay = dtd->part1.v_active;
-       mode->vdisplay += ((dtd->part1.v_high >> 4) & 0x0f) << 8;
-       mode->vsync_start = mode->vdisplay;
-       mode->vsync_start += (dtd->part2.v_sync_off_width >> 4) & 0xf;
-       mode->vsync_start += (dtd->part2.sync_off_width_high & 0x0c) << 2;
-       mode->vsync_start += dtd->part2.v_sync_off_high & 0xc0;
-       mode->vsync_end = mode->vsync_start +
+       struct drm_display_mode mode = {};
+
+       mode.hdisplay = dtd->part1.h_active;
+       mode.hdisplay += ((dtd->part1.h_high >> 4) & 0x0f) << 8;
+       mode.hsync_start = mode.hdisplay + dtd->part2.h_sync_off;
+       mode.hsync_start += (dtd->part2.sync_off_width_high & 0xc0) << 2;
+       mode.hsync_end = mode.hsync_start + dtd->part2.h_sync_width;
+       mode.hsync_end += (dtd->part2.sync_off_width_high & 0x30) << 4;
+       mode.htotal = mode.hdisplay + dtd->part1.h_blank;
+       mode.htotal += (dtd->part1.h_high & 0xf) << 8;
+
+       mode.vdisplay = dtd->part1.v_active;
+       mode.vdisplay += ((dtd->part1.v_high >> 4) & 0x0f) << 8;
+       mode.vsync_start = mode.vdisplay;
+       mode.vsync_start += (dtd->part2.v_sync_off_width >> 4) & 0xf;
+       mode.vsync_start += (dtd->part2.sync_off_width_high & 0x0c) << 2;
+       mode.vsync_start += dtd->part2.v_sync_off_high & 0xc0;
+       mode.vsync_end = mode.vsync_start +
                (dtd->part2.v_sync_off_width & 0xf);
-       mode->vsync_end += (dtd->part2.sync_off_width_high & 0x3) << 4;
-       mode->vtotal = mode->vdisplay + dtd->part1.v_blank;
-       mode->vtotal += (dtd->part1.v_high & 0xf) << 8;
+       mode.vsync_end += (dtd->part2.sync_off_width_high & 0x3) << 4;
+       mode.vtotal = mode.vdisplay + dtd->part1.v_blank;
+       mode.vtotal += (dtd->part1.v_high & 0xf) << 8;
 
-       mode->clock = dtd->part1.clock * 10;
+       mode.clock = dtd->part1.clock * 10;
 
-       mode->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
        if (dtd->part2.dtd_flags & DTD_FLAG_INTERLACE)
-               mode->flags |= DRM_MODE_FLAG_INTERLACE;
+               mode.flags |= DRM_MODE_FLAG_INTERLACE;
        if (dtd->part2.dtd_flags & DTD_FLAG_HSYNC_POSITIVE)
-               mode->flags |= DRM_MODE_FLAG_PHSYNC;
+               mode.flags |= DRM_MODE_FLAG_PHSYNC;
+       else
+               mode.flags |= DRM_MODE_FLAG_NHSYNC;
        if (dtd->part2.dtd_flags & DTD_FLAG_VSYNC_POSITIVE)
-               mode->flags |= DRM_MODE_FLAG_PVSYNC;
+               mode.flags |= DRM_MODE_FLAG_PVSYNC;
+       else
+               mode.flags |= DRM_MODE_FLAG_NVSYNC;
+
+       drm_mode_set_crtcinfo(&mode, 0);
+
+       drm_mode_copy(pmode, &mode);
 }
 
 static bool intel_sdvo_check_supp_encode(struct intel_sdvo *intel_sdvo)
index f2c6d7909ae2d66ffa73ebe77d7c3b06d46403f7..dd6f84bf6c220e94c7f50e1d38ca7fea9f11cecb 100644 (file)
@@ -916,6 +916,14 @@ intel_tv_compute_config(struct intel_encoder *encoder,
        DRM_DEBUG_KMS("forcing bpc to 8 for TV\n");
        pipe_config->pipe_bpp = 8*3;
 
+       /* TV has it's own notion of sync and other mode flags, so clear them. */
+       pipe_config->adjusted_mode.flags = 0;
+
+       /*
+        * FIXME: We don't check whether the input mode is actually what we want
+        * or whether userspace is doing something stupid.
+        */
+
        return true;
 }
 
index a60584763b61dde085f39c8058e4cb6900e2bace..a0b9d8a95b16c17ad6b11ae1b6da662e80484b04 100644 (file)
@@ -124,6 +124,8 @@ void adreno_recover(struct msm_gpu *gpu)
 
        /* reset completed fence seqno, just discard anything pending: */
        adreno_gpu->memptrs->fence = gpu->submitted_fence;
+       adreno_gpu->memptrs->rptr  = 0;
+       adreno_gpu->memptrs->wptr  = 0;
 
        gpu->funcs->pm_resume(gpu);
        ret = gpu->funcs->hw_init(gpu);
@@ -229,7 +231,7 @@ void adreno_idle(struct msm_gpu *gpu)
                        return;
        } while(time_before(jiffies, t));
 
-       DRM_ERROR("timeout waiting for %s to drain ringbuffer!\n", gpu->name);
+       DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name);
 
        /* TODO maybe we need to reset GPU here to recover from hang? */
 }
@@ -256,11 +258,17 @@ void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords)
 {
        struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
        uint32_t freedwords;
+       unsigned long t = jiffies + ADRENO_IDLE_TIMEOUT;
        do {
                uint32_t size = gpu->rb->size / 4;
                uint32_t wptr = get_wptr(gpu->rb);
                uint32_t rptr = adreno_gpu->memptrs->rptr;
                freedwords = (rptr + (size - 1) - wptr) % size;
+
+               if (time_after(jiffies, t)) {
+                       DRM_ERROR("%s: timeout waiting for ringbuffer space\n", gpu->name);
+                       break;
+               }
        } while(freedwords < ndwords);
 }
 
index 5db5bbaedae21d64b9764fc8d009dfa86b862543..bc7fd11ad8be4e7d4785d0f696d128220f25b7ca 100644 (file)
@@ -19,8 +19,6 @@
 #include "msm_drv.h"
 #include "mdp4_kms.h"
 
-#include <mach/iommu.h>
-
 static struct mdp4_platform_config *mdp4_get_config(struct platform_device *dev);
 
 static int mdp4_hw_init(struct msm_kms *kms)
index 864c9773636baf6aa7173c6b16a5f81841a2b922..b3a2f16290417cb055a8d7d89dc8f3f876b3a090 100644 (file)
@@ -18,8 +18,6 @@
 #include "msm_drv.h"
 #include "msm_gpu.h"
 
-#include <mach/iommu.h>
-
 static void msm_fb_output_poll_changed(struct drm_device *dev)
 {
        struct msm_drm_private *priv = dev->dev_private;
@@ -62,6 +60,8 @@ int msm_iommu_attach(struct drm_device *dev, struct iommu_domain *iommu,
        int i, ret;
 
        for (i = 0; i < cnt; i++) {
+               /* TODO maybe some day msm iommu won't require this hack: */
+               struct device *msm_iommu_get_ctx(const char *ctx_name);
                struct device *ctx = msm_iommu_get_ctx(names[i]);
                if (!ctx)
                        continue;
@@ -199,7 +199,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
                 * imx drm driver on iMX5
                 */
                dev_err(dev->dev, "failed to load kms\n");
-               ret = PTR_ERR(priv->kms);
+               ret = PTR_ERR(kms);
                goto fail;
        }
 
@@ -499,25 +499,41 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
                struct timespec *timeout)
 {
        struct msm_drm_private *priv = dev->dev_private;
-       unsigned long timeout_jiffies = timespec_to_jiffies(timeout);
-       unsigned long start_jiffies = jiffies;
-       unsigned long remaining_jiffies;
        int ret;
 
-       if (time_after(start_jiffies, timeout_jiffies))
-               remaining_jiffies = 0;
-       else
-               remaining_jiffies = timeout_jiffies - start_jiffies;
-
-       ret = wait_event_interruptible_timeout(priv->fence_event,
-                       priv->completed_fence >= fence,
-                       remaining_jiffies);
-       if (ret == 0) {
-               DBG("timeout waiting for fence: %u (completed: %u)",
-                               fence, priv->completed_fence);
-               ret = -ETIMEDOUT;
-       } else if (ret != -ERESTARTSYS) {
-               ret = 0;
+       if (!priv->gpu)
+               return 0;
+
+       if (fence > priv->gpu->submitted_fence) {
+               DRM_ERROR("waiting on invalid fence: %u (of %u)\n",
+                               fence, priv->gpu->submitted_fence);
+               return -EINVAL;
+       }
+
+       if (!timeout) {
+               /* no-wait: */
+               ret = fence_completed(dev, fence) ? 0 : -EBUSY;
+       } else {
+               unsigned long timeout_jiffies = timespec_to_jiffies(timeout);
+               unsigned long start_jiffies = jiffies;
+               unsigned long remaining_jiffies;
+
+               if (time_after(start_jiffies, timeout_jiffies))
+                       remaining_jiffies = 0;
+               else
+                       remaining_jiffies = timeout_jiffies - start_jiffies;
+
+               ret = wait_event_interruptible_timeout(priv->fence_event,
+                               fence_completed(dev, fence),
+                               remaining_jiffies);
+
+               if (ret == 0) {
+                       DBG("timeout waiting for fence: %u (completed: %u)",
+                                       fence, priv->completed_fence);
+                       ret = -ETIMEDOUT;
+               } else if (ret != -ERESTARTSYS) {
+                       ret = 0;
+               }
        }
 
        return ret;
@@ -681,7 +697,7 @@ static struct drm_driver msm_driver = {
        .gem_vm_ops         = &vm_ops,
        .dumb_create        = msm_gem_dumb_create,
        .dumb_map_offset    = msm_gem_dumb_map_offset,
-       .dumb_destroy       = msm_gem_dumb_destroy,
+       .dumb_destroy       = drm_gem_dumb_destroy,
 #ifdef CONFIG_DEBUG_FS
        .debugfs_init       = msm_debugfs_init,
        .debugfs_cleanup    = msm_debugfs_cleanup,
index 80d75094bf0afd9bb24cb34971cd5622259717ca..df8f1d084bc1d76d1ee8dc5db948e7ebf9f87771 100644 (file)
@@ -153,7 +153,7 @@ void *msm_gem_vaddr(struct drm_gem_object *obj);
 int msm_gem_queue_inactive_work(struct drm_gem_object *obj,
                struct work_struct *work);
 void msm_gem_move_to_active(struct drm_gem_object *obj,
-               struct msm_gpu *gpu, uint32_t fence);
+               struct msm_gpu *gpu, bool write, uint32_t fence);
 void msm_gem_move_to_inactive(struct drm_gem_object *obj);
 int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op,
                struct timespec *timeout);
@@ -191,6 +191,12 @@ u32 msm_readl(const void __iomem *addr);
 #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
 #define VERB(fmt, ...) if (0) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
 
+static inline bool fence_completed(struct drm_device *dev, uint32_t fence)
+{
+       struct msm_drm_private *priv = dev->dev_private;
+       return priv->completed_fence >= fence;
+}
+
 static inline int align_pitch(int width, int bpp)
 {
        int bytespp = (bpp + 7) / 8;
index 6b5a6c8c7658c5b91e905ac013779d022d299cfe..2bae46c66a30dd4c3eac623c07dbf55c70d32cb8 100644 (file)
@@ -40,9 +40,9 @@ static struct page **get_pages(struct drm_gem_object *obj)
                }
 
                msm_obj->sgt = drm_prime_pages_to_sg(p, npages);
-               if (!msm_obj->sgt) {
+               if (IS_ERR(msm_obj->sgt)) {
                        dev_err(dev->dev, "failed to allocate sgt\n");
-                       return ERR_PTR(-ENOMEM);
+                       return ERR_CAST(msm_obj->sgt);
                }
 
                msm_obj->pages = p;
@@ -159,7 +159,6 @@ out_unlock:
 out:
        switch (ret) {
        case -EAGAIN:
-               set_need_resched();
        case 0:
        case -ERESTARTSYS:
        case -EINTR:
@@ -320,13 +319,6 @@ int msm_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
                        MSM_BO_SCANOUT | MSM_BO_WC, &args->handle);
 }
 
-int msm_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
-               uint32_t handle)
-{
-       /* No special work needed, drop the reference and see what falls out */
-       return drm_gem_handle_delete(file, handle);
-}
-
 int msm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
                uint32_t handle, uint64_t *offset)
 {
@@ -393,11 +385,14 @@ int msm_gem_queue_inactive_work(struct drm_gem_object *obj,
 }
 
 void msm_gem_move_to_active(struct drm_gem_object *obj,
-               struct msm_gpu *gpu, uint32_t fence)
+               struct msm_gpu *gpu, bool write, uint32_t fence)
 {
        struct msm_gem_object *msm_obj = to_msm_bo(obj);
        msm_obj->gpu = gpu;
-       msm_obj->fence = fence;
+       if (write)
+               msm_obj->write_fence = fence;
+       else
+               msm_obj->read_fence = fence;
        list_del_init(&msm_obj->mm_list);
        list_add_tail(&msm_obj->mm_list, &gpu->active_list);
 }
@@ -411,7 +406,8 @@ void msm_gem_move_to_inactive(struct drm_gem_object *obj)
        WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
        msm_obj->gpu = NULL;
-       msm_obj->fence = 0;
+       msm_obj->read_fence = 0;
+       msm_obj->write_fence = 0;
        list_del_init(&msm_obj->mm_list);
        list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
 
@@ -433,8 +429,18 @@ int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op,
        struct msm_gem_object *msm_obj = to_msm_bo(obj);
        int ret = 0;
 
-       if (is_active(msm_obj) && !(op & MSM_PREP_NOSYNC))
-               ret = msm_wait_fence_interruptable(dev, msm_obj->fence, timeout);
+       if (is_active(msm_obj)) {
+               uint32_t fence = 0;
+
+               if (op & MSM_PREP_READ)
+                       fence = msm_obj->write_fence;
+               if (op & MSM_PREP_WRITE)
+                       fence = max(fence, msm_obj->read_fence);
+               if (op & MSM_PREP_NOSYNC)
+                       timeout = NULL;
+
+               ret = msm_wait_fence_interruptable(dev, fence, timeout);
+       }
 
        /* TODO cache maintenance */
 
@@ -455,9 +461,10 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
        uint64_t off = drm_vma_node_start(&obj->vma_node);
 
        WARN_ON(!mutex_is_locked(&dev->struct_mutex));
-       seq_printf(m, "%08x: %c(%d) %2d (%2d) %08llx %p %d\n",
+       seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %p %d\n",
                        msm_obj->flags, is_active(msm_obj) ? 'A' : 'I',
-                       msm_obj->fence, obj->name, obj->refcount.refcount.counter,
+                       msm_obj->read_fence, msm_obj->write_fence,
+                       obj->name, obj->refcount.refcount.counter,
                        off, msm_obj->vaddr, obj->size);
 }
 
index d746f13d283c8cdaf7d885b2cd52e254a98f6061..0676f32e2c6ab917fe9980380c82137a1ad8f7ce 100644 (file)
@@ -36,7 +36,7 @@ struct msm_gem_object {
         */
        struct list_head mm_list;
        struct msm_gpu *gpu;     /* non-null if active */
-       uint32_t fence;
+       uint32_t read_fence, write_fence;
 
        /* Transiently in the process of submit ioctl, objects associated
         * with the submit are on submit->bo_list.. this only lasts for
index 3e1ef3a00f60cc929555768c1cb963b0b265e251..5281d4bc37f750e2162e4bd1f17859e4921c45cc 100644 (file)
@@ -78,7 +78,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
                }
 
                if (submit_bo.flags & BO_INVALID_FLAGS) {
-                       DBG("invalid flags: %x", submit_bo.flags);
+                       DRM_ERROR("invalid flags: %x\n", submit_bo.flags);
                        ret = -EINVAL;
                        goto out_unlock;
                }
@@ -92,7 +92,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
                 */
                obj = idr_find(&file->object_idr, submit_bo.handle);
                if (!obj) {
-                       DBG("invalid handle %u at index %u", submit_bo.handle, i);
+                       DRM_ERROR("invalid handle %u at index %u\n", submit_bo.handle, i);
                        ret = -EINVAL;
                        goto out_unlock;
                }
@@ -100,7 +100,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
                msm_obj = to_msm_bo(obj);
 
                if (!list_empty(&msm_obj->submit_entry)) {
-                       DBG("handle %u at index %u already on submit list",
+                       DRM_ERROR("handle %u at index %u already on submit list\n",
                                        submit_bo.handle, i);
                        ret = -EINVAL;
                        goto out_unlock;
@@ -216,8 +216,9 @@ static int submit_bo(struct msm_gem_submit *submit, uint32_t idx,
                struct msm_gem_object **obj, uint32_t *iova, bool *valid)
 {
        if (idx >= submit->nr_bos) {
-               DBG("invalid buffer index: %u (out of %u)", idx, submit->nr_bos);
-               return EINVAL;
+               DRM_ERROR("invalid buffer index: %u (out of %u)\n",
+                               idx, submit->nr_bos);
+               return -EINVAL;
        }
 
        if (obj)
@@ -239,7 +240,7 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
        int ret;
 
        if (offset % 4) {
-               DBG("non-aligned cmdstream buffer: %u", offset);
+               DRM_ERROR("non-aligned cmdstream buffer: %u\n", offset);
                return -EINVAL;
        }
 
@@ -266,7 +267,7 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
                        return -EFAULT;
 
                if (submit_reloc.submit_offset % 4) {
-                       DBG("non-aligned reloc offset: %u",
+                       DRM_ERROR("non-aligned reloc offset: %u\n",
                                        submit_reloc.submit_offset);
                        return -EINVAL;
                }
@@ -276,7 +277,7 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
 
                if ((off >= (obj->base.size / 4)) ||
                                (off < last_offset)) {
-                       DBG("invalid offset %u at reloc %u", off, i);
+                       DRM_ERROR("invalid offset %u at reloc %u\n", off, i);
                        return -EINVAL;
                }
 
@@ -374,14 +375,15 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
                        goto out;
 
                if (submit_cmd.size % 4) {
-                       DBG("non-aligned cmdstream buffer size: %u",
+                       DRM_ERROR("non-aligned cmdstream buffer size: %u\n",
                                        submit_cmd.size);
                        ret = -EINVAL;
                        goto out;
                }
 
-               if (submit_cmd.size >= msm_obj->base.size) {
-                       DBG("invalid cmdstream size: %u", submit_cmd.size);
+               if ((submit_cmd.size + submit_cmd.submit_offset) >=
+                               msm_obj->base.size) {
+                       DRM_ERROR("invalid cmdstream size: %u\n", submit_cmd.size);
                        ret = -EINVAL;
                        goto out;
                }
index e1e1ec9321ffe5d8db74e53a5d52b8a4122a51d9..3bab937965d1f596405864676464fe6370bf87bd 100644 (file)
 static void bs_init(struct msm_gpu *gpu, struct platform_device *pdev)
 {
        struct drm_device *dev = gpu->dev;
-       struct kgsl_device_platform_data *pdata = pdev->dev.platform_data;
+       struct kgsl_device_platform_data *pdata;
 
        if (!pdev) {
                dev_err(dev->dev, "could not find dtv pdata\n");
                return;
        }
 
+       pdata = pdev->dev.platform_data;
        if (pdata->bus_scale_table) {
                gpu->bsc = msm_bus_scale_register_client(pdata->bus_scale_table);
                DBG("bus scale client: %08x", gpu->bsc);
@@ -230,6 +231,8 @@ static void hangcheck_timer_reset(struct msm_gpu *gpu)
 static void hangcheck_handler(unsigned long data)
 {
        struct msm_gpu *gpu = (struct msm_gpu *)data;
+       struct drm_device *dev = gpu->dev;
+       struct msm_drm_private *priv = dev->dev_private;
        uint32_t fence = gpu->funcs->last_fence(gpu);
 
        if (fence != gpu->hangcheck_fence) {
@@ -237,14 +240,22 @@ static void hangcheck_handler(unsigned long data)
                gpu->hangcheck_fence = fence;
        } else if (fence < gpu->submitted_fence) {
                /* no progress and not done.. hung! */
-               struct msm_drm_private *priv = gpu->dev->dev_private;
                gpu->hangcheck_fence = fence;
+               dev_err(dev->dev, "%s: hangcheck detected gpu lockup!\n",
+                               gpu->name);
+               dev_err(dev->dev, "%s:     completed fence: %u\n",
+                               gpu->name, fence);
+               dev_err(dev->dev, "%s:     submitted fence: %u\n",
+                               gpu->name, gpu->submitted_fence);
                queue_work(priv->wq, &gpu->recover_work);
        }
 
        /* if still more pending work, reset the hangcheck timer: */
        if (gpu->submitted_fence > gpu->hangcheck_fence)
                hangcheck_timer_reset(gpu);
+
+       /* workaround for missing irq: */
+       queue_work(priv->wq, &gpu->retire_work);
 }
 
 /*
@@ -265,7 +276,8 @@ static void retire_worker(struct work_struct *work)
                obj = list_first_entry(&gpu->active_list,
                                struct msm_gem_object, mm_list);
 
-               if (obj->fence <= fence) {
+               if ((obj->read_fence <= fence) &&
+                               (obj->write_fence <= fence)) {
                        /* move to inactive: */
                        msm_gem_move_to_inactive(&obj->base);
                        msm_gem_put_iova(&obj->base, gpu->id);
@@ -321,7 +333,11 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
                                        submit->gpu->id, &iova);
                }
 
-               msm_gem_move_to_active(&msm_obj->base, gpu, submit->fence);
+               if (submit->bos[i].flags & MSM_SUBMIT_BO_READ)
+                       msm_gem_move_to_active(&msm_obj->base, gpu, false, submit->fence);
+
+               if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)
+                       msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence);
        }
        hangcheck_timer_reset(gpu);
        mutex_unlock(&dev->struct_mutex);
index 2e11ea02cf879ea1d99dcb6c45450bd821bbb13f..57cda2a1437b0d2076d0661d5202ec73337e0ad8 100644 (file)
@@ -579,8 +579,22 @@ static void
 init_reserved(struct nvbios_init *init)
 {
        u8 opcode = nv_ro08(init->bios, init->offset);
-       trace("RESERVED\t0x%02x\n", opcode);
-       init->offset += 1;
+       u8 length, i;
+
+       switch (opcode) {
+       case 0xaa:
+               length = 4;
+               break;
+       default:
+               length = 1;
+               break;
+       }
+
+       trace("RESERVED 0x%02x\t", opcode);
+       for (i = 1; i < length; i++)
+               cont(" 0x%02x", nv_ro08(init->bios, init->offset + i));
+       cont("\n");
+       init->offset += length;
 }
 
 /**
@@ -1437,7 +1451,7 @@ init_configure_mem(struct nvbios_init *init)
        data = init_rdvgai(init, 0x03c4, 0x01);
        init_wrvgai(init, 0x03c4, 0x01, data | 0x20);
 
-       while ((addr = nv_ro32(bios, sdata)) != 0xffffffff) {
+       for (; (addr = nv_ro32(bios, sdata)) != 0xffffffff; sdata += 4) {
                switch (addr) {
                case 0x10021c: /* CKE_NORMAL */
                case 0x1002d0: /* CMD_REFRESH */
@@ -2135,6 +2149,7 @@ static struct nvbios_init_opcode {
        [0x99] = { init_zm_auxch },
        [0x9a] = { init_i2c_long_if },
        [0xa9] = { init_gpio_ne },
+       [0xaa] = { init_reserved },
 };
 
 #define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0]))
index d2712e6e5d313030baeaa4873a1553def7bffe93..7848590f5568e4142457a0f121d9282ca6d1ae17 100644 (file)
@@ -278,7 +278,6 @@ nouveau_display_create(struct drm_device *dev)
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_display *disp;
-       u32 pclass = dev->pdev->class >> 8;
        int ret, gen;
 
        disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL);
@@ -340,29 +339,25 @@ nouveau_display_create(struct drm_device *dev)
        drm_kms_helper_poll_init(dev);
        drm_kms_helper_poll_disable(dev);
 
-       if (nouveau_modeset == 1 ||
-           (nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) {
-               if (drm->vbios.dcb.entries) {
-                       if (nv_device(drm->device)->card_type < NV_50)
-                               ret = nv04_display_create(dev);
-                       else
-                               ret = nv50_display_create(dev);
-               } else {
-                       ret = 0;
-               }
-
-               if (ret)
-                       goto disp_create_err;
+       if (drm->vbios.dcb.entries) {
+               if (nv_device(drm->device)->card_type < NV_50)
+                       ret = nv04_display_create(dev);
+               else
+                       ret = nv50_display_create(dev);
+       } else {
+               ret = 0;
+       }
 
-               if (dev->mode_config.num_crtc) {
-                       ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
-                       if (ret)
-                               goto vblank_err;
-               }
+       if (ret)
+               goto disp_create_err;
 
-               nouveau_backlight_init(dev);
+       if (dev->mode_config.num_crtc) {
+               ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+               if (ret)
+                       goto vblank_err;
        }
 
+       nouveau_backlight_init(dev);
        return 0;
 
 vblank_err:
index 8f6d63d7edd314c4f6a6ff7e492c3b37be88930e..a86ecf65c1642b2372e9a0e0136a69c7b068e041 100644 (file)
@@ -454,7 +454,8 @@ nouveau_fbcon_init(struct drm_device *dev)
        int preferred_bpp;
        int ret;
 
-       if (!dev->mode_config.num_crtc)
+       if (!dev->mode_config.num_crtc ||
+           (dev->pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
                return 0;
 
        fbcon = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL);
index ca5492ac2da53bb792425f4d0ae9c0758d0cde96..0843ebc910d4d6062ce94023f70dde1f1cc00ea0 100644 (file)
@@ -104,9 +104,7 @@ nouveau_sgdma_create_ttm(struct ttm_bo_device *bdev,
        else
                nvbe->ttm.ttm.func = &nv50_sgdma_backend;
 
-       if (ttm_dma_tt_init(&nvbe->ttm, bdev, size, page_flags, dummy_read_page)) {
-               kfree(nvbe);
+       if (ttm_dma_tt_init(&nvbe->ttm, bdev, size, page_flags, dummy_read_page))
                return NULL;
-       }
        return &nvbe->ttm.ttm;
 }
index acf667859cb6231040914270b5bafbc923004ea8..701c4c10e08b5858a5e083d05329af23c076669e 100644 (file)
@@ -664,8 +664,9 @@ static int omap_dmm_probe(struct platform_device *dev)
        }
 
        /* set dma mask for device */
-       /* NOTE: this is a workaround for the hwmod not initializing properly */
-       dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_set_coherent_mask(&dev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               goto fail;
 
        omap_dmm->dummy_pa = page_to_phys(omap_dmm->dummy_page);
 
index dfac7965ea28002b562a4838e143c9ea66501e93..32923d2f60021105a5092826bcd7810ca054c960 100644 (file)
@@ -707,8 +707,9 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
        switch (connector->connector_type) {
        case DRM_MODE_CONNECTOR_DVII:
        case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
-               if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
-                   radeon_audio)
+               if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) ||
+                   (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+                    (radeon_connector->audio == RADEON_AUDIO_AUTO)))
                        return ATOM_ENCODER_MODE_HDMI;
                else if (radeon_connector->use_digital)
                        return ATOM_ENCODER_MODE_DVI;
@@ -718,8 +719,9 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
        case DRM_MODE_CONNECTOR_DVID:
        case DRM_MODE_CONNECTOR_HDMIA:
        default:
-               if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
-                   radeon_audio)
+               if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) ||
+                   (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+                    (radeon_connector->audio == RADEON_AUDIO_AUTO)))
                        return ATOM_ENCODER_MODE_HDMI;
                else
                        return ATOM_ENCODER_MODE_DVI;
@@ -732,8 +734,9 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
                if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
                    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
                        return ATOM_ENCODER_MODE_DP;
-               else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
-                        radeon_audio)
+               else if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) ||
+                        (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+                         (radeon_connector->audio == RADEON_AUDIO_AUTO)))
                        return ATOM_ENCODER_MODE_HDMI;
                else
                        return ATOM_ENCODER_MODE_DVI;
@@ -1647,8 +1650,12 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
                        atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
-                       /* some early dce3.2 boards have a bug in their transmitter control table */
-                       if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730))
+                       /* some dce3.x boards have a bug in their transmitter control table.
+                        * ACTION_ENABLE_OUTPUT can probably be dropped since ACTION_ENABLE
+                        * does the same thing and more.
+                        */
+                       if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730) &&
+                           (rdev->family != CHIP_RS880))
                                atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
                }
                if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
index 084e69414fd15405d03417b0e73ab8e8f1488c58..b162e98a2953ee392029dba8c1eae7d0e3678e97 100644 (file)
@@ -1168,6 +1168,23 @@ static const struct radeon_blacklist_clocks btc_blacklist_clocks[] =
         { 25000, 30000, RADEON_SCLK_UP }
 };
 
+void btc_get_max_clock_from_voltage_dependency_table(struct radeon_clock_voltage_dependency_table *table,
+                                                    u32 *max_clock)
+{
+       u32 i, clock = 0;
+
+       if ((table == NULL) || (table->count == 0)) {
+               *max_clock = clock;
+               return;
+       }
+
+       for (i = 0; i < table->count; i++) {
+               if (clock < table->entries[i].clk)
+                       clock = table->entries[i].clk;
+       }
+       *max_clock = clock;
+}
+
 void btc_apply_voltage_dependency_rules(struct radeon_clock_voltage_dependency_table *table,
                                        u32 clock, u16 max_voltage, u16 *voltage)
 {
@@ -2080,6 +2097,7 @@ static void btc_apply_state_adjust_rules(struct radeon_device *rdev,
        bool disable_mclk_switching;
        u32 mclk, sclk;
        u16 vddc, vddci;
+       u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;
 
        if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
            btc_dpm_vblank_too_short(rdev))
@@ -2121,6 +2139,39 @@ static void btc_apply_state_adjust_rules(struct radeon_device *rdev,
                        ps->low.vddci = max_limits->vddci;
        }
 
+       /* limit clocks to max supported clocks based on voltage dependency tables */
+       btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
+                                                       &max_sclk_vddc);
+       btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
+                                                       &max_mclk_vddci);
+       btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
+                                                       &max_mclk_vddc);
+
+       if (max_sclk_vddc) {
+               if (ps->low.sclk > max_sclk_vddc)
+                       ps->low.sclk = max_sclk_vddc;
+               if (ps->medium.sclk > max_sclk_vddc)
+                       ps->medium.sclk = max_sclk_vddc;
+               if (ps->high.sclk > max_sclk_vddc)
+                       ps->high.sclk = max_sclk_vddc;
+       }
+       if (max_mclk_vddci) {
+               if (ps->low.mclk > max_mclk_vddci)
+                       ps->low.mclk = max_mclk_vddci;
+               if (ps->medium.mclk > max_mclk_vddci)
+                       ps->medium.mclk = max_mclk_vddci;
+               if (ps->high.mclk > max_mclk_vddci)
+                       ps->high.mclk = max_mclk_vddci;
+       }
+       if (max_mclk_vddc) {
+               if (ps->low.mclk > max_mclk_vddc)
+                       ps->low.mclk = max_mclk_vddc;
+               if (ps->medium.mclk > max_mclk_vddc)
+                       ps->medium.mclk = max_mclk_vddc;
+               if (ps->high.mclk > max_mclk_vddc)
+                       ps->high.mclk = max_mclk_vddc;
+       }
+
        /* XXX validate the min clocks required for display */
 
        if (disable_mclk_switching) {
@@ -2340,12 +2391,6 @@ int btc_dpm_set_power_state(struct radeon_device *rdev)
                return ret;
        }
 
-       ret = rv770_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO);
-       if (ret) {
-               DRM_ERROR("rv770_dpm_force_performance_level failed\n");
-               return ret;
-       }
-
        return 0;
 }
 
index 1a15e0e41950604ec8c27df9b11c6933c43d622d..3b6f12b7760ba48066f2144b73e0dc82c6521946 100644 (file)
@@ -46,6 +46,8 @@ void btc_adjust_clock_combinations(struct radeon_device *rdev,
                                   struct rv7xx_pl *pl);
 void btc_apply_voltage_dependency_rules(struct radeon_clock_voltage_dependency_table *table,
                                        u32 clock, u16 max_voltage, u16 *voltage);
+void btc_get_max_clock_from_voltage_dependency_table(struct radeon_clock_voltage_dependency_table *table,
+                                                    u32 *max_clock);
 void btc_apply_voltage_delta_rules(struct radeon_device *rdev,
                                   u16 max_vddc, u16 max_vddci,
                                   u16 *vddc, u16 *vddci);
index 3cce533397c6583e345bd27cc79bd6b725926097..51e947a97edf945d02594dc0731b098ac033e1e0 100644 (file)
@@ -146,6 +146,8 @@ static const struct ci_pt_config_reg didt_config_ci[] =
 };
 
 extern u8 rv770_get_memory_module_index(struct radeon_device *rdev);
+extern void btc_get_max_clock_from_voltage_dependency_table(struct radeon_clock_voltage_dependency_table *table,
+                                                           u32 *max_clock);
 extern int ni_copy_and_switch_arb_sets(struct radeon_device *rdev,
                                       u32 arb_freq_src, u32 arb_freq_dest);
 extern u8 si_get_ddr3_mclk_frequency_ratio(u32 memory_clock);
@@ -712,6 +714,7 @@ static void ci_apply_state_adjust_rules(struct radeon_device *rdev,
        struct radeon_clock_and_voltage_limits *max_limits;
        bool disable_mclk_switching;
        u32 sclk, mclk;
+       u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;
        int i;
 
        if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
@@ -739,6 +742,29 @@ static void ci_apply_state_adjust_rules(struct radeon_device *rdev,
                }
        }
 
+       /* limit clocks to max supported clocks based on voltage dependency tables */
+       btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
+                                                       &max_sclk_vddc);
+       btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
+                                                       &max_mclk_vddci);
+       btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
+                                                       &max_mclk_vddc);
+
+       for (i = 0; i < ps->performance_level_count; i++) {
+               if (max_sclk_vddc) {
+                       if (ps->performance_levels[i].sclk > max_sclk_vddc)
+                               ps->performance_levels[i].sclk = max_sclk_vddc;
+               }
+               if (max_mclk_vddci) {
+                       if (ps->performance_levels[i].mclk > max_mclk_vddci)
+                               ps->performance_levels[i].mclk = max_mclk_vddci;
+               }
+               if (max_mclk_vddc) {
+                       if (ps->performance_levels[i].mclk > max_mclk_vddc)
+                               ps->performance_levels[i].mclk = max_mclk_vddc;
+               }
+       }
+
        /* XXX validate the min clocks required for display */
 
        if (disable_mclk_switching) {
@@ -4748,12 +4774,6 @@ int ci_dpm_set_power_state(struct radeon_device *rdev)
        if (pi->pcie_performance_request)
                ci_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps);
 
-       ret = ci_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO);
-       if (ret) {
-               DRM_ERROR("ci_dpm_force_performance_level failed\n");
-               return ret;
-       }
-
        cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
                             RADEON_CG_BLOCK_MC |
                             RADEON_CG_BLOCK_SDMA |
index 53b43dd3cf1eb40d5dffcab0e5f0376346e0f14b..252e10a41cf5a065872ee50597a7e5f2b2e3035d 100644 (file)
@@ -47,10 +47,11 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev,
                         u32 smc_start_address,
                         const u8 *src, u32 byte_count, u32 limit)
 {
+       unsigned long flags;
        u32 data, original_data;
        u32 addr;
        u32 extra_shift;
-       int ret;
+       int ret = 0;
 
        if (smc_start_address & 3)
                return -EINVAL;
@@ -59,13 +60,14 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev,
 
        addr = smc_start_address;
 
+       spin_lock_irqsave(&rdev->smc_idx_lock, flags);
        while (byte_count >= 4) {
                /* SMC address space is BE */
                data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
 
                ret = ci_set_smc_sram_address(rdev, addr, limit);
                if (ret)
-                       return ret;
+                       goto done;
 
                WREG32(SMC_IND_DATA_0, data);
 
@@ -80,7 +82,7 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev,
 
                ret = ci_set_smc_sram_address(rdev, addr, limit);
                if (ret)
-                       return ret;
+                       goto done;
 
                original_data = RREG32(SMC_IND_DATA_0);
 
@@ -97,11 +99,15 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev,
 
                ret = ci_set_smc_sram_address(rdev, addr, limit);
                if (ret)
-                       return ret;
+                       goto done;
 
                WREG32(SMC_IND_DATA_0, data);
        }
-       return 0;
+
+done:
+       spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
+
+       return ret;
 }
 
 void ci_start_smc(struct radeon_device *rdev)
@@ -197,6 +203,7 @@ PPSMC_Result ci_wait_for_smc_inactive(struct radeon_device *rdev)
 
 int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
 {
+       unsigned long flags;
        u32 ucode_start_address;
        u32 ucode_size;
        const u8 *src;
@@ -219,6 +226,7 @@ int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
                return -EINVAL;
 
        src = (const u8 *)rdev->smc_fw->data;
+       spin_lock_irqsave(&rdev->smc_idx_lock, flags);
        WREG32(SMC_IND_INDEX_0, ucode_start_address);
        WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0);
        while (ucode_size >= 4) {
@@ -231,6 +239,7 @@ int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
                ucode_size -= 4;
        }
        WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0);
+       spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
 
        return 0;
 }
@@ -238,25 +247,29 @@ int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
 int ci_read_smc_sram_dword(struct radeon_device *rdev,
                           u32 smc_address, u32 *value, u32 limit)
 {
+       unsigned long flags;
        int ret;
 
+       spin_lock_irqsave(&rdev->smc_idx_lock, flags);
        ret = ci_set_smc_sram_address(rdev, smc_address, limit);
-       if (ret)
-               return ret;
+       if (ret == 0)
+               *value = RREG32(SMC_IND_DATA_0);
+       spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
 
-       *value = RREG32(SMC_IND_DATA_0);
-       return 0;
+       return ret;
 }
 
 int ci_write_smc_sram_dword(struct radeon_device *rdev,
                            u32 smc_address, u32 value, u32 limit)
 {
+       unsigned long flags;
        int ret;
 
+       spin_lock_irqsave(&rdev->smc_idx_lock, flags);
        ret = ci_set_smc_sram_address(rdev, smc_address, limit);
-       if (ret)
-               return ret;
+       if (ret == 0)
+               WREG32(SMC_IND_DATA_0, value);
+       spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
 
-       WREG32(SMC_IND_DATA_0, value);
-       return 0;
+       return ret;
 }
index a3bba05872769fa77d1561681de9639aae95acf9..d02fd1c045d567371a187c686e1af2b411f88aa1 100644 (file)
@@ -77,6 +77,8 @@ static void cik_pcie_gen3_enable(struct radeon_device *rdev);
 static void cik_program_aspm(struct radeon_device *rdev);
 static void cik_init_pg(struct radeon_device *rdev);
 static void cik_init_cg(struct radeon_device *rdev);
+static void cik_enable_gui_idle_interrupt(struct radeon_device *rdev,
+                                         bool enable);
 
 /* get temperature in millidegrees */
 int ci_get_temp(struct radeon_device *rdev)
@@ -120,20 +122,27 @@ int kv_get_temp(struct radeon_device *rdev)
  */
 u32 cik_pciep_rreg(struct radeon_device *rdev, u32 reg)
 {
+       unsigned long flags;
        u32 r;
 
+       spin_lock_irqsave(&rdev->pciep_idx_lock, flags);
        WREG32(PCIE_INDEX, reg);
        (void)RREG32(PCIE_INDEX);
        r = RREG32(PCIE_DATA);
+       spin_unlock_irqrestore(&rdev->pciep_idx_lock, flags);
        return r;
 }
 
 void cik_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->pciep_idx_lock, flags);
        WREG32(PCIE_INDEX, reg);
        (void)RREG32(PCIE_INDEX);
        WREG32(PCIE_DATA, v);
        (void)RREG32(PCIE_DATA);
+       spin_unlock_irqrestore(&rdev->pciep_idx_lock, flags);
 }
 
 static const u32 spectre_rlc_save_restore_register_list[] =
@@ -2722,7 +2731,8 @@ static void cik_gpu_init(struct radeon_device *rdev)
                } else if ((rdev->pdev->device == 0x1309) ||
                           (rdev->pdev->device == 0x130A) ||
                           (rdev->pdev->device == 0x130D) ||
-                          (rdev->pdev->device == 0x1313)) {
+                          (rdev->pdev->device == 0x1313) ||
+                          (rdev->pdev->device == 0x131D)) {
                        rdev->config.cik.max_cu_per_sh = 6;
                        rdev->config.cik.max_backends_per_se = 2;
                } else if ((rdev->pdev->device == 0x1306) ||
@@ -2835,10 +2845,8 @@ static void cik_gpu_init(struct radeon_device *rdev)
                rdev->config.cik.tile_config |= (3 << 0);
                break;
        }
-       if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT)
-               rdev->config.cik.tile_config |= 1 << 4;
-       else
-               rdev->config.cik.tile_config |= 0 << 4;
+       rdev->config.cik.tile_config |=
+               ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4;
        rdev->config.cik.tile_config |=
                ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8;
        rdev->config.cik.tile_config |=
@@ -4013,6 +4021,8 @@ static int cik_cp_resume(struct radeon_device *rdev)
 {
        int r;
 
+       cik_enable_gui_idle_interrupt(rdev, false);
+
        r = cik_cp_load_microcode(rdev);
        if (r)
                return r;
@@ -4024,6 +4034,8 @@ static int cik_cp_resume(struct radeon_device *rdev)
        if (r)
                return r;
 
+       cik_enable_gui_idle_interrupt(rdev, true);
+
        return 0;
 }
 
@@ -4442,8 +4454,8 @@ static int cik_mc_init(struct radeon_device *rdev)
        rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0);
        rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0);
        /* size in MB on si */
-       rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
-       rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
+       rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
+       rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
        rdev->mc.visible_vram_size = rdev->mc.aper_size;
        si_vram_gtt_location(rdev, &rdev->mc);
        radeon_update_bandwidth_info(rdev);
@@ -4721,12 +4733,13 @@ static void cik_vm_decode_fault(struct radeon_device *rdev,
        u32 mc_id = (status & MEMORY_CLIENT_ID_MASK) >> MEMORY_CLIENT_ID_SHIFT;
        u32 vmid = (status & FAULT_VMID_MASK) >> FAULT_VMID_SHIFT;
        u32 protections = (status & PROTECTIONS_MASK) >> PROTECTIONS_SHIFT;
-       char *block = (char *)&mc_client;
+       char block[5] = { mc_client >> 24, (mc_client >> 16) & 0xff,
+               (mc_client >> 8) & 0xff, mc_client & 0xff, 0 };
 
-       printk("VM fault (0x%02x, vmid %d) at page %u, %s from %s (%d)\n",
+       printk("VM fault (0x%02x, vmid %d) at page %u, %s from '%s' (0x%08x) (%d)\n",
               protections, vmid, addr,
               (status & MEMORY_CLIENT_RW_MASK) ? "write" : "read",
-              block, mc_id);
+              block, mc_client, mc_id);
 }
 
 /**
@@ -5376,7 +5389,9 @@ static void cik_enable_hdp_ls(struct radeon_device *rdev,
 void cik_update_cg(struct radeon_device *rdev,
                   u32 block, bool enable)
 {
+
        if (block & RADEON_CG_BLOCK_GFX) {
+               cik_enable_gui_idle_interrupt(rdev, false);
                /* order matters! */
                if (enable) {
                        cik_enable_mgcg(rdev, true);
@@ -5385,6 +5400,7 @@ void cik_update_cg(struct radeon_device *rdev,
                        cik_enable_cgcg(rdev, false);
                        cik_enable_mgcg(rdev, false);
                }
+               cik_enable_gui_idle_interrupt(rdev, true);
        }
 
        if (block & RADEON_CG_BLOCK_MC) {
@@ -5541,7 +5557,7 @@ static void cik_enable_gfx_cgpg(struct radeon_device *rdev,
 {
        u32 data, orig;
 
-       if (enable && (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG)) {
+       if (enable && (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG)) {
                orig = data = RREG32(RLC_PG_CNTL);
                data |= GFX_PG_ENABLE;
                if (orig != data)
@@ -5805,7 +5821,7 @@ static void cik_init_pg(struct radeon_device *rdev)
        if (rdev->pg_flags) {
                cik_enable_sck_slowdown_on_pu(rdev, true);
                cik_enable_sck_slowdown_on_pd(rdev, true);
-               if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG) {
+               if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG) {
                        cik_init_gfx_cgpg(rdev);
                        cik_enable_cp_pg(rdev, true);
                        cik_enable_gds_pg(rdev, true);
@@ -5819,7 +5835,7 @@ static void cik_fini_pg(struct radeon_device *rdev)
 {
        if (rdev->pg_flags) {
                cik_update_gfx_pg(rdev, false);
-               if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG) {
+               if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG) {
                        cik_enable_cp_pg(rdev, false);
                        cik_enable_gds_pg(rdev, false);
                }
@@ -5895,7 +5911,9 @@ static void cik_disable_interrupt_state(struct radeon_device *rdev)
        u32 tmp;
 
        /* gfx ring */
-       WREG32(CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
+       tmp = RREG32(CP_INT_CNTL_RING0) &
+               (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
+       WREG32(CP_INT_CNTL_RING0, tmp);
        /* sdma */
        tmp = RREG32(SDMA0_CNTL + SDMA0_REGISTER_OFFSET) & ~TRAP_ENABLE;
        WREG32(SDMA0_CNTL + SDMA0_REGISTER_OFFSET, tmp);
@@ -6036,8 +6054,7 @@ static int cik_irq_init(struct radeon_device *rdev)
  */
 int cik_irq_set(struct radeon_device *rdev)
 {
-       u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE |
-               PRIV_INSTR_INT_ENABLE | PRIV_REG_INT_ENABLE;
+       u32 cp_int_cntl;
        u32 cp_m1p0, cp_m1p1, cp_m1p2, cp_m1p3;
        u32 cp_m2p0, cp_m2p1, cp_m2p2, cp_m2p3;
        u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0;
@@ -6058,6 +6075,10 @@ int cik_irq_set(struct radeon_device *rdev)
                return 0;
        }
 
+       cp_int_cntl = RREG32(CP_INT_CNTL_RING0) &
+               (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
+       cp_int_cntl |= PRIV_INSTR_INT_ENABLE | PRIV_REG_INT_ENABLE;
+
        hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
        hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN;
        hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN;
index 95a66db08d9bedabe1b9564fe53939acc7ecca43..91bb470de0a39e4db9713cb58b356a9b6ccbac86 100644 (file)
@@ -2014,12 +2014,6 @@ int cypress_dpm_set_power_state(struct radeon_device *rdev)
        if (eg_pi->pcie_performance_request)
                cypress_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps);
 
-       ret = rv770_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO);
-       if (ret) {
-               DRM_ERROR("rv770_dpm_force_performance_level failed\n");
-               return ret;
-       }
-
        return 0;
 }
 
index 8953255e894b2524e020fd10b99898eceedfd4c9..85a69d2ea3d2c8d86c9c552902d260dd576ac927 100644 (file)
 static u32 dce6_endpoint_rreg(struct radeon_device *rdev,
                              u32 block_offset, u32 reg)
 {
+       unsigned long flags;
        u32 r;
 
+       spin_lock_irqsave(&rdev->end_idx_lock, flags);
        WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset, reg);
        r = RREG32(AZ_F0_CODEC_ENDPOINT_DATA + block_offset);
+       spin_unlock_irqrestore(&rdev->end_idx_lock, flags);
+
        return r;
 }
 
 static void dce6_endpoint_wreg(struct radeon_device *rdev,
                               u32 block_offset, u32 reg, u32 v)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->end_idx_lock, flags);
        if (ASIC_IS_DCE8(rdev))
                WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset, reg);
        else
                WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset,
                       AZ_ENDPOINT_REG_WRITE_EN | AZ_ENDPOINT_REG_INDEX(reg));
        WREG32(AZ_F0_CODEC_ENDPOINT_DATA + block_offset, v);
+       spin_unlock_irqrestore(&rdev->end_idx_lock, flags);
 }
 
 #define RREG32_ENDPOINT(block, reg) dce6_endpoint_rreg(rdev, (block), (reg))
@@ -86,12 +94,12 @@ void dce6_afmt_select_pin(struct drm_encoder *encoder)
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
        u32 offset = dig->afmt->offset;
-       u32 id = dig->afmt->pin->id;
 
        if (!dig->afmt->pin)
                return;
 
-       WREG32(AFMT_AUDIO_SRC_CONTROL + offset, AFMT_AUDIO_SRC_SELECT(id));
+       WREG32(AFMT_AUDIO_SRC_CONTROL + offset,
+              AFMT_AUDIO_SRC_SELECT(dig->afmt->pin->id));
 }
 
 void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
index ecd60809db4ec700910a5451f27b8979febc5ec7..71399065db04d309104b98ede05b69226ad3b271 100644 (file)
@@ -40,6 +40,7 @@ static int kv_calculate_dpm_settings(struct radeon_device *rdev);
 static void kv_enable_new_levels(struct radeon_device *rdev);
 static void kv_program_nbps_index_settings(struct radeon_device *rdev,
                                           struct radeon_ps *new_rps);
+static int kv_set_enabled_level(struct radeon_device *rdev, u32 level);
 static int kv_set_enabled_levels(struct radeon_device *rdev);
 static int kv_force_dpm_highest(struct radeon_device *rdev);
 static int kv_force_dpm_lowest(struct radeon_device *rdev);
@@ -519,7 +520,7 @@ static int kv_set_dpm_boot_state(struct radeon_device *rdev)
 
 static void kv_program_vc(struct radeon_device *rdev)
 {
-       WREG32_SMC(CG_FTV_0, 0x3FFFC000);
+       WREG32_SMC(CG_FTV_0, 0x3FFFC100);
 }
 
 static void kv_clear_vc(struct radeon_device *rdev)
@@ -638,7 +639,10 @@ static int kv_force_lowest_valid(struct radeon_device *rdev)
 
 static int kv_unforce_levels(struct radeon_device *rdev)
 {
-       return kv_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel);
+       if (rdev->family == CHIP_KABINI)
+               return kv_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel);
+       else
+               return kv_set_enabled_levels(rdev);
 }
 
 static int kv_update_sclk_t(struct radeon_device *rdev)
@@ -667,9 +671,8 @@ static int kv_program_bootup_state(struct radeon_device *rdev)
                &rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk;
 
        if (table && table->count) {
-               for (i = pi->graphics_dpm_level_count - 1; i >= 0; i--) {
-                       if ((table->entries[i].clk == pi->boot_pl.sclk) ||
-                           (i == 0))
+               for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) {
+                       if (table->entries[i].clk == pi->boot_pl.sclk)
                                break;
                }
 
@@ -682,9 +685,8 @@ static int kv_program_bootup_state(struct radeon_device *rdev)
                if (table->num_max_dpm_entries == 0)
                        return -EINVAL;
 
-               for (i = pi->graphics_dpm_level_count - 1; i >= 0; i--) {
-                       if ((table->entries[i].sclk_frequency == pi->boot_pl.sclk) ||
-                           (i == 0))
+               for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) {
+                       if (table->entries[i].sclk_frequency == pi->boot_pl.sclk)
                                break;
                }
 
@@ -1078,6 +1080,13 @@ static int kv_enable_ulv(struct radeon_device *rdev, bool enable)
                                        PPSMC_MSG_EnableULV : PPSMC_MSG_DisableULV);
 }
 
+static void kv_reset_acp_boot_level(struct radeon_device *rdev)
+{
+       struct kv_power_info *pi = kv_get_pi(rdev);
+
+       pi->acp_boot_level = 0xff;
+}
+
 static void kv_update_current_ps(struct radeon_device *rdev,
                                 struct radeon_ps *rps)
 {
@@ -1100,6 +1109,18 @@ static void kv_update_requested_ps(struct radeon_device *rdev,
        pi->requested_rps.ps_priv = &pi->requested_ps;
 }
 
+void kv_dpm_enable_bapm(struct radeon_device *rdev, bool enable)
+{
+       struct kv_power_info *pi = kv_get_pi(rdev);
+       int ret;
+
+       if (pi->bapm_enable) {
+               ret = kv_smc_bapm_enable(rdev, enable);
+               if (ret)
+                       DRM_ERROR("kv_smc_bapm_enable failed\n");
+       }
+}
+
 int kv_dpm_enable(struct radeon_device *rdev)
 {
        struct kv_power_info *pi = kv_get_pi(rdev);
@@ -1192,6 +1213,8 @@ int kv_dpm_enable(struct radeon_device *rdev)
                return ret;
        }
 
+       kv_reset_acp_boot_level(rdev);
+
        if (rdev->irq.installed &&
            r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
                ret = kv_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
@@ -1203,6 +1226,12 @@ int kv_dpm_enable(struct radeon_device *rdev)
                radeon_irq_set(rdev);
        }
 
+       ret = kv_smc_bapm_enable(rdev, false);
+       if (ret) {
+               DRM_ERROR("kv_smc_bapm_enable failed\n");
+               return ret;
+       }
+
        /* powerdown unused blocks for now */
        kv_dpm_powergate_acp(rdev, true);
        kv_dpm_powergate_samu(rdev, true);
@@ -1226,6 +1255,8 @@ void kv_dpm_disable(struct radeon_device *rdev)
                             RADEON_CG_BLOCK_BIF |
                             RADEON_CG_BLOCK_HDP), false);
 
+       kv_smc_bapm_enable(rdev, false);
+
        /* powerup blocks */
        kv_dpm_powergate_acp(rdev, false);
        kv_dpm_powergate_samu(rdev, false);
@@ -1450,6 +1481,39 @@ static int kv_update_samu_dpm(struct radeon_device *rdev, bool gate)
        return kv_enable_samu_dpm(rdev, !gate);
 }
 
+static u8 kv_get_acp_boot_level(struct radeon_device *rdev)
+{
+       u8 i;
+       struct radeon_clock_voltage_dependency_table *table =
+               &rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table;
+
+       for (i = 0; i < table->count; i++) {
+               if (table->entries[i].clk >= 0) /* XXX */
+                       break;
+       }
+
+       if (i >= table->count)
+               i = table->count - 1;
+
+       return i;
+}
+
+static void kv_update_acp_boot_level(struct radeon_device *rdev)
+{
+       struct kv_power_info *pi = kv_get_pi(rdev);
+       u8 acp_boot_level;
+
+       if (!pi->caps_stable_p_state) {
+               acp_boot_level = kv_get_acp_boot_level(rdev);
+               if (acp_boot_level != pi->acp_boot_level) {
+                       pi->acp_boot_level = acp_boot_level;
+                       kv_send_msg_to_smc_with_parameter(rdev,
+                                                         PPSMC_MSG_ACPDPM_SetEnabledMask,
+                                                         (1 << pi->acp_boot_level));
+               }
+       }
+}
+
 static int kv_update_acp_dpm(struct radeon_device *rdev, bool gate)
 {
        struct kv_power_info *pi = kv_get_pi(rdev);
@@ -1461,7 +1525,7 @@ static int kv_update_acp_dpm(struct radeon_device *rdev, bool gate)
                if (pi->caps_stable_p_state)
                        pi->acp_boot_level = table->count - 1;
                else
-                       pi->acp_boot_level = 0;
+                       pi->acp_boot_level = kv_get_acp_boot_level(rdev);
 
                ret = kv_copy_bytes_to_smc(rdev,
                                           pi->dpm_table_start +
@@ -1588,13 +1652,11 @@ static void kv_set_valid_clock_range(struct radeon_device *rdev,
                        }
                }
 
-               for (i = pi->graphics_dpm_level_count - 1; i >= 0; i--) {
-                       if ((table->entries[i].clk <= new_ps->levels[new_ps->num_levels -1].sclk) ||
-                           (i == 0)) {
-                               pi->highest_valid = i;
+               for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) {
+                       if (table->entries[i].clk <= new_ps->levels[new_ps->num_levels - 1].sclk)
                                break;
-                       }
                }
+               pi->highest_valid = i;
 
                if (pi->lowest_valid > pi->highest_valid) {
                        if ((new_ps->levels[0].sclk - table->entries[pi->highest_valid].clk) >
@@ -1615,14 +1677,12 @@ static void kv_set_valid_clock_range(struct radeon_device *rdev,
                        }
                }
 
-               for (i = pi->graphics_dpm_level_count - 1; i >= 0; i--) {
+               for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) {
                        if (table->entries[i].sclk_frequency <=
-                           new_ps->levels[new_ps->num_levels - 1].sclk ||
-                           i == 0) {
-                               pi->highest_valid = i;
+                           new_ps->levels[new_ps->num_levels - 1].sclk)
                                break;
-                       }
                }
+               pi->highest_valid = i;
 
                if (pi->lowest_valid > pi->highest_valid) {
                        if ((new_ps->levels[0].sclk -
@@ -1724,6 +1784,14 @@ int kv_dpm_set_power_state(struct radeon_device *rdev)
                             RADEON_CG_BLOCK_BIF |
                             RADEON_CG_BLOCK_HDP), false);
 
+       if (pi->bapm_enable) {
+               ret = kv_smc_bapm_enable(rdev, rdev->pm.dpm.ac_power);
+               if (ret) {
+                       DRM_ERROR("kv_smc_bapm_enable failed\n");
+                       return ret;
+               }
+       }
+
        if (rdev->family == CHIP_KABINI) {
                if (pi->enable_dpm) {
                        kv_set_valid_clock_range(rdev, new_ps);
@@ -1775,6 +1843,7 @@ int kv_dpm_set_power_state(struct radeon_device *rdev)
                                return ret;
                        }
 #endif
+                       kv_update_acp_boot_level(rdev);
                        kv_update_sclk_t(rdev);
                        kv_enable_nb_dpm(rdev);
                }
@@ -1785,7 +1854,6 @@ int kv_dpm_set_power_state(struct radeon_device *rdev)
                             RADEON_CG_BLOCK_BIF |
                             RADEON_CG_BLOCK_HDP), true);
 
-       rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO;
        return 0;
 }
 
@@ -1806,12 +1874,23 @@ void kv_dpm_setup_asic(struct radeon_device *rdev)
 
 void kv_dpm_reset_asic(struct radeon_device *rdev)
 {
-       kv_force_lowest_valid(rdev);
-       kv_init_graphics_levels(rdev);
-       kv_program_bootup_state(rdev);
-       kv_upload_dpm_settings(rdev);
-       kv_force_lowest_valid(rdev);
-       kv_unforce_levels(rdev);
+       struct kv_power_info *pi = kv_get_pi(rdev);
+
+       if (rdev->family == CHIP_KABINI) {
+               kv_force_lowest_valid(rdev);
+               kv_init_graphics_levels(rdev);
+               kv_program_bootup_state(rdev);
+               kv_upload_dpm_settings(rdev);
+               kv_force_lowest_valid(rdev);
+               kv_unforce_levels(rdev);
+       } else {
+               kv_init_graphics_levels(rdev);
+               kv_program_bootup_state(rdev);
+               kv_freeze_sclk_dpm(rdev, true);
+               kv_upload_dpm_settings(rdev);
+               kv_freeze_sclk_dpm(rdev, false);
+               kv_set_enabled_level(rdev, pi->graphics_boot_level);
+       }
 }
 
 //XXX use sumo_dpm_display_configuration_changed
@@ -1871,12 +1950,15 @@ static int kv_force_dpm_highest(struct radeon_device *rdev)
        if (ret)
                return ret;
 
-       for (i = SMU7_MAX_LEVELS_GRAPHICS - 1; i >= 0; i--) {
+       for (i = SMU7_MAX_LEVELS_GRAPHICS - 1; i > 0; i--) {
                if (enable_mask & (1 << i))
                        break;
        }
 
-       return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i);
+       if (rdev->family == CHIP_KABINI)
+               return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i);
+       else
+               return kv_set_enabled_level(rdev, i);
 }
 
 static int kv_force_dpm_lowest(struct radeon_device *rdev)
@@ -1893,7 +1975,10 @@ static int kv_force_dpm_lowest(struct radeon_device *rdev)
                        break;
        }
 
-       return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i);
+       if (rdev->family == CHIP_KABINI)
+               return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i);
+       else
+               return kv_set_enabled_level(rdev, i);
 }
 
 static u8 kv_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
@@ -1911,9 +1996,9 @@ static u8 kv_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
        if (!pi->caps_sclk_ds)
                return 0;
 
-       for (i = KV_MAX_DEEPSLEEP_DIVIDER_ID; i <= 0; i--) {
+       for (i = KV_MAX_DEEPSLEEP_DIVIDER_ID; i > 0; i--) {
                temp = sclk / sumo_get_sleep_divider_from_id(i);
-               if ((temp >= min) || (i == 0))
+               if (temp >= min)
                        break;
        }
 
@@ -2039,12 +2124,12 @@ static void kv_apply_state_adjust_rules(struct radeon_device *rdev,
                ps->dpmx_nb_ps_lo = 0x1;
                ps->dpmx_nb_ps_hi = 0x0;
        } else {
-               ps->dpm0_pg_nb_ps_lo = 0x1;
+               ps->dpm0_pg_nb_ps_lo = 0x3;
                ps->dpm0_pg_nb_ps_hi = 0x0;
-               ps->dpmx_nb_ps_lo = 0x2;
-               ps->dpmx_nb_ps_hi = 0x1;
+               ps->dpmx_nb_ps_lo = 0x3;
+               ps->dpmx_nb_ps_hi = 0x0;
 
-               if (pi->sys_info.nb_dpm_enable && pi->battery_state) {
+               if (pi->sys_info.nb_dpm_enable) {
                        force_high = (mclk >= pi->sys_info.nbp_memory_clock[3]) ||
                                pi->video_start || (rdev->pm.dpm.new_active_crtc_count >= 3) ||
                                pi->disable_nb_ps3_in_battery;
@@ -2210,6 +2295,15 @@ static void kv_enable_new_levels(struct radeon_device *rdev)
        }
 }
 
+static int kv_set_enabled_level(struct radeon_device *rdev, u32 level)
+{
+       u32 new_mask = (1 << level);
+
+       return kv_send_msg_to_smc_with_parameter(rdev,
+                                                PPSMC_MSG_SCLKDPM_SetEnabledMask,
+                                                new_mask);
+}
+
 static int kv_set_enabled_levels(struct radeon_device *rdev)
 {
        struct kv_power_info *pi = kv_get_pi(rdev);
index 32bb079572d757ab7b58309a506cf113ce2d1e41..8cef7525d7a87500f07ad709cd203c481d7b4350 100644 (file)
@@ -192,6 +192,7 @@ int kv_send_msg_to_smc_with_parameter(struct radeon_device *rdev,
 int kv_read_smc_sram_dword(struct radeon_device *rdev, u32 smc_address,
                           u32 *value, u32 limit);
 int kv_smc_dpm_enable(struct radeon_device *rdev, bool enable);
+int kv_smc_bapm_enable(struct radeon_device *rdev, bool enable);
 int kv_copy_bytes_to_smc(struct radeon_device *rdev,
                         u32 smc_start_address,
                         const u8 *src, u32 byte_count, u32 limit);
index 34a226d7e34aafc72649d77854f4e3a3a3844912..0000b59a6d0599c4c0e080f2a58815ee6c3e8f43 100644 (file)
@@ -107,6 +107,14 @@ int kv_smc_dpm_enable(struct radeon_device *rdev, bool enable)
                return kv_notify_message_to_smu(rdev, PPSMC_MSG_DPM_Disable);
 }
 
+int kv_smc_bapm_enable(struct radeon_device *rdev, bool enable)
+{
+       if (enable)
+               return kv_notify_message_to_smu(rdev, PPSMC_MSG_EnableBAPM);
+       else
+               return kv_notify_message_to_smu(rdev, PPSMC_MSG_DisableBAPM);
+}
+
 int kv_copy_bytes_to_smc(struct radeon_device *rdev,
                         u32 smc_start_address,
                         const u8 *src, u32 byte_count, u32 limit)
index f7b625c9e0e9cfa355ad27b0f1f2952bc9de8427..f26339028154274609f31247580d03cbbed0d312 100644 (file)
@@ -787,6 +787,7 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev,
        bool disable_mclk_switching;
        u32 mclk, sclk;
        u16 vddc, vddci;
+       u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;
        int i;
 
        if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
@@ -813,6 +814,29 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev,
                }
        }
 
+       /* limit clocks to max supported clocks based on voltage dependency tables */
+       btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
+                                                       &max_sclk_vddc);
+       btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
+                                                       &max_mclk_vddci);
+       btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
+                                                       &max_mclk_vddc);
+
+       for (i = 0; i < ps->performance_level_count; i++) {
+               if (max_sclk_vddc) {
+                       if (ps->performance_levels[i].sclk > max_sclk_vddc)
+                               ps->performance_levels[i].sclk = max_sclk_vddc;
+               }
+               if (max_mclk_vddci) {
+                       if (ps->performance_levels[i].mclk > max_mclk_vddci)
+                               ps->performance_levels[i].mclk = max_mclk_vddci;
+               }
+               if (max_mclk_vddc) {
+                       if (ps->performance_levels[i].mclk > max_mclk_vddc)
+                               ps->performance_levels[i].mclk = max_mclk_vddc;
+               }
+       }
+
        /* XXX validate the min clocks required for display */
 
        if (disable_mclk_switching) {
@@ -3865,12 +3889,6 @@ int ni_dpm_set_power_state(struct radeon_device *rdev)
                return ret;
        }
 
-       ret = ni_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO);
-       if (ret) {
-               DRM_ERROR("ni_dpm_force_performance_level failed\n");
-               return ret;
-       }
-
        return 0;
 }
 
index 682842804bce3e47ffe5d961a0125747f132d6e1..5670b8291285d6827e87abd7a66b447ee774d315 100644 (file)
@@ -163,6 +163,8 @@ typedef uint8_t PPSMC_Result;
 #define PPSMC_MSG_VCEPowerON                ((uint32_t) 0x10f)
 #define PPSMC_MSG_DCE_RemoveVoltageAdjustment   ((uint32_t) 0x11d)
 #define PPSMC_MSG_DCE_AllowVoltageAdjustment    ((uint32_t) 0x11e)
+#define PPSMC_MSG_EnableBAPM                ((uint32_t) 0x120)
+#define PPSMC_MSG_DisableBAPM               ((uint32_t) 0x121)
 #define PPSMC_MSG_UVD_DPM_Config            ((uint32_t) 0x124)
 
 
index 9fc61dd68bc073b4b2fd82976caef85f66696c9c..d71333033b2ba0bc63f9e710a23f710d7b96b066 100644 (file)
@@ -2853,21 +2853,28 @@ static void r100_pll_errata_after_data(struct radeon_device *rdev)
 
 uint32_t r100_pll_rreg(struct radeon_device *rdev, uint32_t reg)
 {
+       unsigned long flags;
        uint32_t data;
 
+       spin_lock_irqsave(&rdev->pll_idx_lock, flags);
        WREG8(RADEON_CLOCK_CNTL_INDEX, reg & 0x3f);
        r100_pll_errata_after_index(rdev);
        data = RREG32(RADEON_CLOCK_CNTL_DATA);
        r100_pll_errata_after_data(rdev);
+       spin_unlock_irqrestore(&rdev->pll_idx_lock, flags);
        return data;
 }
 
 void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->pll_idx_lock, flags);
        WREG8(RADEON_CLOCK_CNTL_INDEX, ((reg & 0x3f) | RADEON_PLL_WR_EN));
        r100_pll_errata_after_index(rdev);
        WREG32(RADEON_CLOCK_CNTL_DATA, v);
        r100_pll_errata_after_data(rdev);
+       spin_unlock_irqrestore(&rdev->pll_idx_lock, flags);
 }
 
 static void r100_set_safe_registers(struct radeon_device *rdev)
@@ -2926,9 +2933,11 @@ static int r100_debugfs_cp_ring_info(struct seq_file *m, void *data)
        seq_printf(m, "CP_RB_RPTR 0x%08x\n", rdp);
        seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw);
        seq_printf(m, "%u dwords in ring\n", count);
-       for (j = 0; j <= count; j++) {
-               i = (rdp + j) & ring->ptr_mask;
-               seq_printf(m, "r[%04d]=0x%08x\n", i, ring->ring[i]);
+       if (ring->ready) {
+               for (j = 0; j <= count; j++) {
+                       i = (rdp + j) & ring->ptr_mask;
+                       seq_printf(m, "r[%04d]=0x%08x\n", i, ring->ring[i]);
+               }
        }
        return 0;
 }
index 4e796ecf9ea4770e2388a56032cd135f5e861605..6edf2b3a52b4d7e4ba82cc063048ffb73733a984 100644 (file)
@@ -160,18 +160,25 @@ void r420_pipes_init(struct radeon_device *rdev)
 
 u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg)
 {
+       unsigned long flags;
        u32 r;
 
+       spin_lock_irqsave(&rdev->mc_idx_lock, flags);
        WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg));
        r = RREG32(R_0001FC_MC_IND_DATA);
+       spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
        return r;
 }
 
 void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->mc_idx_lock, flags);
        WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg) |
                S_0001F8_MC_IND_WR_EN(1));
        WREG32(R_0001FC_MC_IND_DATA, v);
+       spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
 }
 
 static void r420_debugfs(struct radeon_device *rdev)
index ea4d3734e6d9ce269efa5bb1eb98c7da5bccd819..2a1b1876b4312eb332c017cb027aeb346bf2c850 100644 (file)
@@ -119,6 +119,11 @@ u32 r600_get_xclk(struct radeon_device *rdev)
        return rdev->clock.spll.reference_freq;
 }
 
+int r600_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
+{
+       return 0;
+}
+
 /* get temperature in millidegrees */
 int rv6xx_get_temp(struct radeon_device *rdev)
 {
@@ -1045,20 +1050,27 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev)
 
 uint32_t rs780_mc_rreg(struct radeon_device *rdev, uint32_t reg)
 {
+       unsigned long flags;
        uint32_t r;
 
+       spin_lock_irqsave(&rdev->mc_idx_lock, flags);
        WREG32(R_0028F8_MC_INDEX, S_0028F8_MC_IND_ADDR(reg));
        r = RREG32(R_0028FC_MC_DATA);
        WREG32(R_0028F8_MC_INDEX, ~C_0028F8_MC_IND_ADDR);
+       spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
        return r;
 }
 
 void rs780_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->mc_idx_lock, flags);
        WREG32(R_0028F8_MC_INDEX, S_0028F8_MC_IND_ADDR(reg) |
                S_0028F8_MC_IND_WR_EN(1));
        WREG32(R_0028FC_MC_DATA, v);
        WREG32(R_0028F8_MC_INDEX, 0x7F);
+       spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
 }
 
 static void r600_mc_program(struct radeon_device *rdev)
@@ -2092,20 +2104,27 @@ static void r600_gpu_init(struct radeon_device *rdev)
  */
 u32 r600_pciep_rreg(struct radeon_device *rdev, u32 reg)
 {
+       unsigned long flags;
        u32 r;
 
+       spin_lock_irqsave(&rdev->pciep_idx_lock, flags);
        WREG32(PCIE_PORT_INDEX, ((reg) & 0xff));
        (void)RREG32(PCIE_PORT_INDEX);
        r = RREG32(PCIE_PORT_DATA);
+       spin_unlock_irqrestore(&rdev->pciep_idx_lock, flags);
        return r;
 }
 
 void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->pciep_idx_lock, flags);
        WREG32(PCIE_PORT_INDEX, ((reg) & 0xff));
        (void)RREG32(PCIE_PORT_INDEX);
        WREG32(PCIE_PORT_DATA, (v));
        (void)RREG32(PCIE_PORT_DATA);
+       spin_unlock_irqrestore(&rdev->pciep_idx_lock, flags);
 }
 
 /*
index fa0de46fcc0d1cc5d714f6c8c6cc8e0a958d8001..5513d8f06252e13e11e27e9d21d5aecae775b5a8 100644 (file)
@@ -1084,7 +1084,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev)
                                rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk =
                                        le16_to_cpu(uvd_clk->usDClkLow) | (uvd_clk->ucDClkHigh << 16);
                                rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v =
-                                       le16_to_cpu(limits->entries[i].usVoltage);
+                                       le16_to_cpu(entry->usVoltage);
                                entry = (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *)
                                        ((u8 *)entry + sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record));
                        }
@@ -1219,30 +1219,20 @@ int r600_parse_extended_power_table(struct radeon_device *rdev)
 
 void r600_free_extended_power_table(struct radeon_device *rdev)
 {
-       if (rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries)
-               kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries);
-       if (rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries)
-               kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries);
-       if (rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries)
-               kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries);
-       if (rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries)
-               kfree(rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries);
-       if (rdev->pm.dpm.dyn_state.cac_leakage_table.entries)
-               kfree(rdev->pm.dpm.dyn_state.cac_leakage_table.entries);
-       if (rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries)
-               kfree(rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries);
-       if (rdev->pm.dpm.dyn_state.ppm_table)
-               kfree(rdev->pm.dpm.dyn_state.ppm_table);
-       if (rdev->pm.dpm.dyn_state.cac_tdp_table)
-               kfree(rdev->pm.dpm.dyn_state.cac_tdp_table);
-       if (rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries)
-               kfree(rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries);
-       if (rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries)
-               kfree(rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries);
-       if (rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries)
-               kfree(rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries);
-       if (rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries)
-               kfree(rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries);
+       struct radeon_dpm_dynamic_state *dyn_state = &rdev->pm.dpm.dyn_state;
+
+       kfree(dyn_state->vddc_dependency_on_sclk.entries);
+       kfree(dyn_state->vddci_dependency_on_mclk.entries);
+       kfree(dyn_state->vddc_dependency_on_mclk.entries);
+       kfree(dyn_state->mvdd_dependency_on_mclk.entries);
+       kfree(dyn_state->cac_leakage_table.entries);
+       kfree(dyn_state->phase_shedding_limits_table.entries);
+       kfree(dyn_state->ppm_table);
+       kfree(dyn_state->cac_tdp_table);
+       kfree(dyn_state->vce_clock_voltage_dependency_table.entries);
+       kfree(dyn_state->uvd_clock_voltage_dependency_table.entries);
+       kfree(dyn_state->samu_clock_voltage_dependency_table.entries);
+       kfree(dyn_state->acp_clock_voltage_dependency_table.entries);
 }
 
 enum radeon_pcie_gen r600_get_pcie_gen_support(struct radeon_device *rdev,
index f443010ce90b1ed7607565474b2ba0851e378789..b0fa6002af3e98da440cbebfa1ae183163e8b07d 100644 (file)
@@ -257,10 +257,7 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
         * number (coefficient of two integer numbers.  DCCG_AUDIO_DTOx_PHASE
         * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
         */
-       if (ASIC_IS_DCE3(rdev)) {
-               /* according to the reg specs, this should DCE3.2 only, but in
-                * practice it seems to cover DCE3.0 as well.
-                */
+       if (ASIC_IS_DCE32(rdev)) {
                if (dig->dig_encoder == 0) {
                        dto_cntl = RREG32(DCCG_AUDIO_DTO0_CNTL) & ~DCCG_AUDIO_DTO_WALLCLOCK_RATIO_MASK;
                        dto_cntl |= DCCG_AUDIO_DTO_WALLCLOCK_RATIO(wallclock_ratio);
@@ -276,8 +273,21 @@ void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
                        WREG32(DCCG_AUDIO_DTO1_MODULE, dto_modulo);
                        WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
                }
+       } else if (ASIC_IS_DCE3(rdev)) {
+               /* according to the reg specs, this should DCE3.2 only, but in
+                * practice it seems to cover DCE3.0/3.1 as well.
+                */
+               if (dig->dig_encoder == 0) {
+                       WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100);
+                       WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100);
+                       WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */
+               } else {
+                       WREG32(DCCG_AUDIO_DTO1_PHASE, base_rate * 100);
+                       WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100);
+                       WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
+               }
        } else {
-               /* according to the reg specs, this should be DCE2.0 and DCE3.0 */
+               /* according to the reg specs, this should be DCE2.0 and DCE3.0/3.1 */
                WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate / 10) |
                       AUDIO_DTO_MODULE(clock / 10));
        }
index 454f90a849e47d6ef6e6b87c0bf6c97d3a31b54f..e673fe26ea84d00b292f77c456089c4312372ab7 100644 (file)
 #       define HDMI0_AVI_INFO_CONT   (1 << 1)
 #       define HDMI0_AUDIO_INFO_SEND (1 << 4)
 #       define HDMI0_AUDIO_INFO_CONT (1 << 5)
-#       define HDMI0_AUDIO_INFO_SOURCE (1 << 6) /* 0 - sound block; 1 - hmdi regs */
+#       define HDMI0_AUDIO_INFO_SOURCE (1 << 6) /* 0 - sound block; 1 - hdmi regs */
 #       define HDMI0_AUDIO_INFO_UPDATE (1 << 7)
 #       define HDMI0_MPEG_INFO_SEND  (1 << 8)
 #       define HDMI0_MPEG_INFO_CONT  (1 << 9)
index ff8b564ce2b2d37033de4b4795569beaad0903fa..a400ac1c414715423064874d37f047b426f7fe19 100644 (file)
@@ -181,7 +181,7 @@ extern int radeon_aspm;
 #define RADEON_CG_SUPPORT_HDP_MGCG             (1 << 16)
 
 /* PG flags */
-#define RADEON_PG_SUPPORT_GFX_CG               (1 << 0)
+#define RADEON_PG_SUPPORT_GFX_PG               (1 << 0)
 #define RADEON_PG_SUPPORT_GFX_SMG              (1 << 1)
 #define RADEON_PG_SUPPORT_GFX_DMG              (1 << 2)
 #define RADEON_PG_SUPPORT_UVD                  (1 << 3)
@@ -1778,6 +1778,7 @@ struct radeon_asic {
                int (*force_performance_level)(struct radeon_device *rdev, enum radeon_dpm_forced_level level);
                bool (*vblank_too_short)(struct radeon_device *rdev);
                void (*powergate_uvd)(struct radeon_device *rdev, bool gate);
+               void (*enable_bapm)(struct radeon_device *rdev, bool enable);
        } dpm;
        /* pageflipping */
        struct {
@@ -2110,6 +2111,28 @@ struct radeon_device {
        resource_size_t                 rmmio_size;
        /* protects concurrent MM_INDEX/DATA based register access */
        spinlock_t mmio_idx_lock;
+       /* protects concurrent SMC based register access */
+       spinlock_t smc_idx_lock;
+       /* protects concurrent PLL register access */
+       spinlock_t pll_idx_lock;
+       /* protects concurrent MC register access */
+       spinlock_t mc_idx_lock;
+       /* protects concurrent PCIE register access */
+       spinlock_t pcie_idx_lock;
+       /* protects concurrent PCIE_PORT register access */
+       spinlock_t pciep_idx_lock;
+       /* protects concurrent PIF register access */
+       spinlock_t pif_idx_lock;
+       /* protects concurrent CG register access */
+       spinlock_t cg_idx_lock;
+       /* protects concurrent UVD register access */
+       spinlock_t uvd_idx_lock;
+       /* protects concurrent RCU register access */
+       spinlock_t rcu_idx_lock;
+       /* protects concurrent DIDT register access */
+       spinlock_t didt_idx_lock;
+       /* protects concurrent ENDPOINT (audio) register access */
+       spinlock_t end_idx_lock;
        void __iomem                    *rmmio;
        radeon_rreg_t                   mc_rreg;
        radeon_wreg_t                   mc_wreg;
@@ -2277,123 +2300,179 @@ void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v);
  */
 static inline uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg)
 {
+       unsigned long flags;
        uint32_t r;
 
+       spin_lock_irqsave(&rdev->pcie_idx_lock, flags);
        WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask));
        r = RREG32(RADEON_PCIE_DATA);
+       spin_unlock_irqrestore(&rdev->pcie_idx_lock, flags);
        return r;
 }
 
 static inline void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->pcie_idx_lock, flags);
        WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask));
        WREG32(RADEON_PCIE_DATA, (v));
+       spin_unlock_irqrestore(&rdev->pcie_idx_lock, flags);
 }
 
 static inline u32 tn_smc_rreg(struct radeon_device *rdev, u32 reg)
 {
+       unsigned long flags;
        u32 r;
 
+       spin_lock_irqsave(&rdev->smc_idx_lock, flags);
        WREG32(TN_SMC_IND_INDEX_0, (reg));
        r = RREG32(TN_SMC_IND_DATA_0);
+       spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
        return r;
 }
 
 static inline void tn_smc_wreg(struct radeon_device *rdev, u32 reg, u32 v)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->smc_idx_lock, flags);
        WREG32(TN_SMC_IND_INDEX_0, (reg));
        WREG32(TN_SMC_IND_DATA_0, (v));
+       spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
 }
 
 static inline u32 r600_rcu_rreg(struct radeon_device *rdev, u32 reg)
 {
+       unsigned long flags;
        u32 r;
 
+       spin_lock_irqsave(&rdev->rcu_idx_lock, flags);
        WREG32(R600_RCU_INDEX, ((reg) & 0x1fff));
        r = RREG32(R600_RCU_DATA);
+       spin_unlock_irqrestore(&rdev->rcu_idx_lock, flags);
        return r;
 }
 
 static inline void r600_rcu_wreg(struct radeon_device *rdev, u32 reg, u32 v)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->rcu_idx_lock, flags);
        WREG32(R600_RCU_INDEX, ((reg) & 0x1fff));
        WREG32(R600_RCU_DATA, (v));
+       spin_unlock_irqrestore(&rdev->rcu_idx_lock, flags);
 }
 
 static inline u32 eg_cg_rreg(struct radeon_device *rdev, u32 reg)
 {
+       unsigned long flags;
        u32 r;
 
+       spin_lock_irqsave(&rdev->cg_idx_lock, flags);
        WREG32(EVERGREEN_CG_IND_ADDR, ((reg) & 0xffff));
        r = RREG32(EVERGREEN_CG_IND_DATA);
+       spin_unlock_irqrestore(&rdev->cg_idx_lock, flags);
        return r;
 }
 
 static inline void eg_cg_wreg(struct radeon_device *rdev, u32 reg, u32 v)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->cg_idx_lock, flags);
        WREG32(EVERGREEN_CG_IND_ADDR, ((reg) & 0xffff));
        WREG32(EVERGREEN_CG_IND_DATA, (v));
+       spin_unlock_irqrestore(&rdev->cg_idx_lock, flags);
 }
 
 static inline u32 eg_pif_phy0_rreg(struct radeon_device *rdev, u32 reg)
 {
+       unsigned long flags;
        u32 r;
 
+       spin_lock_irqsave(&rdev->pif_idx_lock, flags);
        WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff));
        r = RREG32(EVERGREEN_PIF_PHY0_DATA);
+       spin_unlock_irqrestore(&rdev->pif_idx_lock, flags);
        return r;
 }
 
 static inline void eg_pif_phy0_wreg(struct radeon_device *rdev, u32 reg, u32 v)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->pif_idx_lock, flags);
        WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff));
        WREG32(EVERGREEN_PIF_PHY0_DATA, (v));
+       spin_unlock_irqrestore(&rdev->pif_idx_lock, flags);
 }
 
 static inline u32 eg_pif_phy1_rreg(struct radeon_device *rdev, u32 reg)
 {
+       unsigned long flags;
        u32 r;
 
+       spin_lock_irqsave(&rdev->pif_idx_lock, flags);
        WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff));
        r = RREG32(EVERGREEN_PIF_PHY1_DATA);
+       spin_unlock_irqrestore(&rdev->pif_idx_lock, flags);
        return r;
 }
 
 static inline void eg_pif_phy1_wreg(struct radeon_device *rdev, u32 reg, u32 v)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->pif_idx_lock, flags);
        WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff));
        WREG32(EVERGREEN_PIF_PHY1_DATA, (v));
+       spin_unlock_irqrestore(&rdev->pif_idx_lock, flags);
 }
 
 static inline u32 r600_uvd_ctx_rreg(struct radeon_device *rdev, u32 reg)
 {
+       unsigned long flags;
        u32 r;
 
+       spin_lock_irqsave(&rdev->uvd_idx_lock, flags);
        WREG32(R600_UVD_CTX_INDEX, ((reg) & 0x1ff));
        r = RREG32(R600_UVD_CTX_DATA);
+       spin_unlock_irqrestore(&rdev->uvd_idx_lock, flags);
        return r;
 }
 
 static inline void r600_uvd_ctx_wreg(struct radeon_device *rdev, u32 reg, u32 v)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->uvd_idx_lock, flags);
        WREG32(R600_UVD_CTX_INDEX, ((reg) & 0x1ff));
        WREG32(R600_UVD_CTX_DATA, (v));
+       spin_unlock_irqrestore(&rdev->uvd_idx_lock, flags);
 }
 
 
 static inline u32 cik_didt_rreg(struct radeon_device *rdev, u32 reg)
 {
+       unsigned long flags;
        u32 r;
 
+       spin_lock_irqsave(&rdev->didt_idx_lock, flags);
        WREG32(CIK_DIDT_IND_INDEX, (reg));
        r = RREG32(CIK_DIDT_IND_DATA);
+       spin_unlock_irqrestore(&rdev->didt_idx_lock, flags);
        return r;
 }
 
 static inline void cik_didt_wreg(struct radeon_device *rdev, u32 reg, u32 v)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->didt_idx_lock, flags);
        WREG32(CIK_DIDT_IND_INDEX, (reg));
        WREG32(CIK_DIDT_IND_DATA, (v));
+       spin_unlock_irqrestore(&rdev->didt_idx_lock, flags);
 }
 
 void r100_pll_errata_after_index(struct radeon_device *rdev);
@@ -2569,6 +2648,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
 #define radeon_dpm_force_performance_level(rdev, l) rdev->asic->dpm.force_performance_level((rdev), (l))
 #define radeon_dpm_vblank_too_short(rdev) rdev->asic->dpm.vblank_too_short((rdev))
 #define radeon_dpm_powergate_uvd(rdev, g) rdev->asic->dpm.powergate_uvd((rdev), (g))
+#define radeon_dpm_enable_bapm(rdev, e) rdev->asic->dpm.enable_bapm((rdev), (e))
 
 /* Common functions */
 /* AGP */
index 630853b96841c2d23e6633981d9efc3ae021f703..8f7e04538fd624a5ecb1c302e8b9d5f2455f808a 100644 (file)
@@ -1004,6 +1004,8 @@ static struct radeon_asic rv6xx_asic = {
                .wait_for_vblank = &avivo_wait_for_vblank,
                .set_backlight_level = &atombios_set_backlight_level,
                .get_backlight_level = &atombios_get_backlight_level,
+               .hdmi_enable = &r600_hdmi_enable,
+               .hdmi_setmode = &r600_hdmi_setmode,
        },
        .copy = {
                .blit = &r600_copy_cpdma,
@@ -1037,6 +1039,7 @@ static struct radeon_asic rv6xx_asic = {
                .set_pcie_lanes = &r600_set_pcie_lanes,
                .set_clock_gating = NULL,
                .get_temperature = &rv6xx_get_temp,
+               .set_uvd_clocks = &r600_set_uvd_clocks,
        },
        .dpm = {
                .init = &rv6xx_dpm_init,
@@ -1126,6 +1129,7 @@ static struct radeon_asic rs780_asic = {
                .set_pcie_lanes = NULL,
                .set_clock_gating = NULL,
                .get_temperature = &rv6xx_get_temp,
+               .set_uvd_clocks = &r600_set_uvd_clocks,
        },
        .dpm = {
                .init = &rs780_dpm_init,
@@ -1141,6 +1145,7 @@ static struct radeon_asic rs780_asic = {
                .get_mclk = &rs780_dpm_get_mclk,
                .print_power_state = &rs780_dpm_print_power_state,
                .debugfs_print_current_performance_level = &rs780_dpm_debugfs_print_current_performance_level,
+               .force_performance_level = &rs780_dpm_force_performance_level,
        },
        .pflip = {
                .pre_page_flip = &rs600_pre_page_flip,
@@ -1791,6 +1796,7 @@ static struct radeon_asic trinity_asic = {
                .print_power_state = &trinity_dpm_print_power_state,
                .debugfs_print_current_performance_level = &trinity_dpm_debugfs_print_current_performance_level,
                .force_performance_level = &trinity_dpm_force_performance_level,
+               .enable_bapm = &trinity_dpm_enable_bapm,
        },
        .pflip = {
                .pre_page_flip = &evergreen_pre_page_flip,
@@ -2166,6 +2172,7 @@ static struct radeon_asic kv_asic = {
                .debugfs_print_current_performance_level = &kv_dpm_debugfs_print_current_performance_level,
                .force_performance_level = &kv_dpm_force_performance_level,
                .powergate_uvd = &kv_dpm_powergate_uvd,
+               .enable_bapm = &kv_dpm_enable_bapm,
        },
        .pflip = {
                .pre_page_flip = &evergreen_pre_page_flip,
@@ -2390,7 +2397,7 @@ int radeon_asic_init(struct radeon_device *rdev)
                                RADEON_CG_SUPPORT_HDP_LS |
                                RADEON_CG_SUPPORT_HDP_MGCG;
                        rdev->pg_flags = 0 |
-                               /*RADEON_PG_SUPPORT_GFX_CG | */
+                               /*RADEON_PG_SUPPORT_GFX_PG | */
                                RADEON_PG_SUPPORT_SDMA;
                        break;
                case CHIP_OLAND:
@@ -2479,7 +2486,7 @@ int radeon_asic_init(struct radeon_device *rdev)
                                RADEON_CG_SUPPORT_HDP_LS |
                                RADEON_CG_SUPPORT_HDP_MGCG;
                        rdev->pg_flags = 0;
-                               /*RADEON_PG_SUPPORT_GFX_CG |
+                               /*RADEON_PG_SUPPORT_GFX_PG |
                                RADEON_PG_SUPPORT_GFX_SMG |
                                RADEON_PG_SUPPORT_GFX_DMG |
                                RADEON_PG_SUPPORT_UVD |
@@ -2507,7 +2514,7 @@ int radeon_asic_init(struct radeon_device *rdev)
                                RADEON_CG_SUPPORT_HDP_LS |
                                RADEON_CG_SUPPORT_HDP_MGCG;
                        rdev->pg_flags = 0;
-                               /*RADEON_PG_SUPPORT_GFX_CG |
+                               /*RADEON_PG_SUPPORT_GFX_PG |
                                RADEON_PG_SUPPORT_GFX_SMG |
                                RADEON_PG_SUPPORT_UVD |
                                RADEON_PG_SUPPORT_VCE |
index 818bbe6b884b309c6ac24d0907ab89cc8d5b5041..70c29d5e080dfffdf1a3511e12e0a663c7a57a8f 100644 (file)
@@ -389,6 +389,7 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev);
 u32 r600_get_xclk(struct radeon_device *rdev);
 uint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev);
 int rv6xx_get_temp(struct radeon_device *rdev);
+int r600_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
 int r600_dpm_pre_set_power_state(struct radeon_device *rdev);
 void r600_dpm_post_set_power_state(struct radeon_device *rdev);
 /* r600 dma */
@@ -428,6 +429,8 @@ void rs780_dpm_print_power_state(struct radeon_device *rdev,
                                 struct radeon_ps *ps);
 void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
                                                       struct seq_file *m);
+int rs780_dpm_force_performance_level(struct radeon_device *rdev,
+                                     enum radeon_dpm_forced_level level);
 
 /*
  * rv770,rv730,rv710,rv740
@@ -625,6 +628,7 @@ void trinity_dpm_debugfs_print_current_performance_level(struct radeon_device *r
                                                         struct seq_file *m);
 int trinity_dpm_force_performance_level(struct radeon_device *rdev,
                                        enum radeon_dpm_forced_level level);
+void trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable);
 
 /* DCE6 - SI */
 void dce6_bandwidth_update(struct radeon_device *rdev);
@@ -781,6 +785,7 @@ void kv_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
 int kv_dpm_force_performance_level(struct radeon_device *rdev,
                                   enum radeon_dpm_forced_level level);
 void kv_dpm_powergate_uvd(struct radeon_device *rdev, bool gate);
+void kv_dpm_enable_bapm(struct radeon_device *rdev, bool enable);
 
 /* uvd v1.0 */
 uint32_t uvd_v1_0_get_rptr(struct radeon_device *rdev,
index 404e25d285ba816b1f34308ce79537b8a0d44a90..f79ee184ffd5849f4d0e0ec1b87b0d94d0f1f131 100644 (file)
@@ -1367,6 +1367,7 @@ bool radeon_atombios_get_ppll_ss_info(struct radeon_device *rdev,
        int index = GetIndexIntoMasterTable(DATA, PPLL_SS_Info);
        uint16_t data_offset, size;
        struct _ATOM_SPREAD_SPECTRUM_INFO *ss_info;
+       struct _ATOM_SPREAD_SPECTRUM_ASSIGNMENT *ss_assign;
        uint8_t frev, crev;
        int i, num_indices;
 
@@ -1378,18 +1379,21 @@ bool radeon_atombios_get_ppll_ss_info(struct radeon_device *rdev,
 
                num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
                        sizeof(ATOM_SPREAD_SPECTRUM_ASSIGNMENT);
-
+               ss_assign = (struct _ATOM_SPREAD_SPECTRUM_ASSIGNMENT*)
+                       ((u8 *)&ss_info->asSS_Info[0]);
                for (i = 0; i < num_indices; i++) {
-                       if (ss_info->asSS_Info[i].ucSS_Id == id) {
+                       if (ss_assign->ucSS_Id == id) {
                                ss->percentage =
-                                       le16_to_cpu(ss_info->asSS_Info[i].usSpreadSpectrumPercentage);
-                               ss->type = ss_info->asSS_Info[i].ucSpreadSpectrumType;
-                               ss->step = ss_info->asSS_Info[i].ucSS_Step;
-                               ss->delay = ss_info->asSS_Info[i].ucSS_Delay;
-                               ss->range = ss_info->asSS_Info[i].ucSS_Range;
-                               ss->refdiv = ss_info->asSS_Info[i].ucRecommendedRef_Div;
+                                       le16_to_cpu(ss_assign->usSpreadSpectrumPercentage);
+                               ss->type = ss_assign->ucSpreadSpectrumType;
+                               ss->step = ss_assign->ucSS_Step;
+                               ss->delay = ss_assign->ucSS_Delay;
+                               ss->range = ss_assign->ucSS_Range;
+                               ss->refdiv = ss_assign->ucRecommendedRef_Div;
                                return true;
                        }
+                       ss_assign = (struct _ATOM_SPREAD_SPECTRUM_ASSIGNMENT*)
+                               ((u8 *)ss_assign + sizeof(struct _ATOM_SPREAD_SPECTRUM_ASSIGNMENT));
                }
        }
        return false;
@@ -1477,6 +1481,12 @@ union asic_ss_info {
        struct _ATOM_ASIC_INTERNAL_SS_INFO_V3 info_3;
 };
 
+union asic_ss_assignment {
+       struct _ATOM_ASIC_SS_ASSIGNMENT v1;
+       struct _ATOM_ASIC_SS_ASSIGNMENT_V2 v2;
+       struct _ATOM_ASIC_SS_ASSIGNMENT_V3 v3;
+};
+
 bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev,
                                      struct radeon_atom_ss *ss,
                                      int id, u32 clock)
@@ -1485,6 +1495,7 @@ bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev,
        int index = GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info);
        uint16_t data_offset, size;
        union asic_ss_info *ss_info;
+       union asic_ss_assignment *ss_assign;
        uint8_t frev, crev;
        int i, num_indices;
 
@@ -1509,45 +1520,52 @@ bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev,
                        num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
                                sizeof(ATOM_ASIC_SS_ASSIGNMENT);
 
+                       ss_assign = (union asic_ss_assignment *)((u8 *)&ss_info->info.asSpreadSpectrum[0]);
                        for (i = 0; i < num_indices; i++) {
-                               if ((ss_info->info.asSpreadSpectrum[i].ucClockIndication == id) &&
-                                   (clock <= le32_to_cpu(ss_info->info.asSpreadSpectrum[i].ulTargetClockRange))) {
+                               if ((ss_assign->v1.ucClockIndication == id) &&
+                                   (clock <= le32_to_cpu(ss_assign->v1.ulTargetClockRange))) {
                                        ss->percentage =
-                                               le16_to_cpu(ss_info->info.asSpreadSpectrum[i].usSpreadSpectrumPercentage);
-                                       ss->type = ss_info->info.asSpreadSpectrum[i].ucSpreadSpectrumMode;
-                                       ss->rate = le16_to_cpu(ss_info->info.asSpreadSpectrum[i].usSpreadRateInKhz);
+                                               le16_to_cpu(ss_assign->v1.usSpreadSpectrumPercentage);
+                                       ss->type = ss_assign->v1.ucSpreadSpectrumMode;
+                                       ss->rate = le16_to_cpu(ss_assign->v1.usSpreadRateInKhz);
                                        return true;
                                }
+                               ss_assign = (union asic_ss_assignment *)
+                                       ((u8 *)ss_assign + sizeof(ATOM_ASIC_SS_ASSIGNMENT));
                        }
                        break;
                case 2:
                        num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
                                sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2);
+                       ss_assign = (union asic_ss_assignment *)((u8 *)&ss_info->info_2.asSpreadSpectrum[0]);
                        for (i = 0; i < num_indices; i++) {
-                               if ((ss_info->info_2.asSpreadSpectrum[i].ucClockIndication == id) &&
-                                   (clock <= le32_to_cpu(ss_info->info_2.asSpreadSpectrum[i].ulTargetClockRange))) {
+                               if ((ss_assign->v2.ucClockIndication == id) &&
+                                   (clock <= le32_to_cpu(ss_assign->v2.ulTargetClockRange))) {
                                        ss->percentage =
-                                               le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadSpectrumPercentage);
-                                       ss->type = ss_info->info_2.asSpreadSpectrum[i].ucSpreadSpectrumMode;
-                                       ss->rate = le16_to_cpu(ss_info->info_2.asSpreadSpectrum[i].usSpreadRateIn10Hz);
+                                               le16_to_cpu(ss_assign->v2.usSpreadSpectrumPercentage);
+                                       ss->type = ss_assign->v2.ucSpreadSpectrumMode;
+                                       ss->rate = le16_to_cpu(ss_assign->v2.usSpreadRateIn10Hz);
                                        if ((crev == 2) &&
                                            ((id == ASIC_INTERNAL_ENGINE_SS) ||
                                             (id == ASIC_INTERNAL_MEMORY_SS)))
                                                ss->rate /= 100;
                                        return true;
                                }
+                               ss_assign = (union asic_ss_assignment *)
+                                       ((u8 *)ss_assign + sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2));
                        }
                        break;
                case 3:
                        num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) /
                                sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
+                       ss_assign = (union asic_ss_assignment *)((u8 *)&ss_info->info_3.asSpreadSpectrum[0]);
                        for (i = 0; i < num_indices; i++) {
-                               if ((ss_info->info_3.asSpreadSpectrum[i].ucClockIndication == id) &&
-                                   (clock <= le32_to_cpu(ss_info->info_3.asSpreadSpectrum[i].ulTargetClockRange))) {
+                               if ((ss_assign->v3.ucClockIndication == id) &&
+                                   (clock <= le32_to_cpu(ss_assign->v3.ulTargetClockRange))) {
                                        ss->percentage =
-                                               le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadSpectrumPercentage);
-                                       ss->type = ss_info->info_3.asSpreadSpectrum[i].ucSpreadSpectrumMode;
-                                       ss->rate = le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadRateIn10Hz);
+                                               le16_to_cpu(ss_assign->v3.usSpreadSpectrumPercentage);
+                                       ss->type = ss_assign->v3.ucSpreadSpectrumMode;
+                                       ss->rate = le16_to_cpu(ss_assign->v3.usSpreadRateIn10Hz);
                                        if ((id == ASIC_INTERNAL_ENGINE_SS) ||
                                            (id == ASIC_INTERNAL_MEMORY_SS))
                                                ss->rate /= 100;
@@ -1555,6 +1573,8 @@ bool radeon_atombios_get_asic_ss_info(struct radeon_device *rdev,
                                                radeon_atombios_get_igp_ss_overrides(rdev, ss, id);
                                        return true;
                                }
+                               ss_assign = (union asic_ss_assignment *)
+                                       ((u8 *)ss_assign + sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3));
                        }
                        break;
                default:
index 2399f25ec0370cfba03b256174de69e407e01353..79159b5da05bc778dc71b819a32c4139d28f967b 100644 (file)
@@ -396,6 +396,21 @@ static int radeon_connector_set_property(struct drm_connector *connector, struct
                }
        }
 
+       if (property == rdev->mode_info.audio_property) {
+               struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+               /* need to find digital encoder on connector */
+               encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
+               if (!encoder)
+                       return 0;
+
+               radeon_encoder = to_radeon_encoder(encoder);
+
+               if (radeon_connector->audio != val) {
+                       radeon_connector->audio = val;
+                       radeon_property_change_mode(&radeon_encoder->base);
+               }
+       }
+
        if (property == rdev->mode_info.underscan_property) {
                /* need to find digital encoder on connector */
                encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
@@ -1420,7 +1435,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
                                if (radeon_dp_getdpcd(radeon_connector))
                                        ret = connector_status_connected;
                        } else {
-                               /* try non-aux ddc (DP to DVI/HMDI/etc. adapter) */
+                               /* try non-aux ddc (DP to DVI/HDMI/etc. adapter) */
                                if (radeon_ddc_probe(radeon_connector, false))
                                        ret = connector_status_connected;
                        }
@@ -1489,6 +1504,24 @@ static const struct drm_connector_funcs radeon_dp_connector_funcs = {
        .force = radeon_dvi_force,
 };
 
+static const struct drm_connector_funcs radeon_edp_connector_funcs = {
+       .dpms = drm_helper_connector_dpms,
+       .detect = radeon_dp_detect,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .set_property = radeon_lvds_set_property,
+       .destroy = radeon_dp_connector_destroy,
+       .force = radeon_dvi_force,
+};
+
+static const struct drm_connector_funcs radeon_lvds_bridge_connector_funcs = {
+       .dpms = drm_helper_connector_dpms,
+       .detect = radeon_dp_detect,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .set_property = radeon_lvds_set_property,
+       .destroy = radeon_dp_connector_destroy,
+       .force = radeon_dvi_force,
+};
+
 void
 radeon_add_atom_connector(struct drm_device *dev,
                          uint32_t connector_id,
@@ -1580,8 +1613,6 @@ radeon_add_atom_connector(struct drm_device *dev,
                        goto failed;
                radeon_dig_connector->igp_lane_info = igp_lane_info;
                radeon_connector->con_priv = radeon_dig_connector;
-               drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type);
-               drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs);
                if (i2c_bus->valid) {
                        /* add DP i2c bus */
                        if (connector_type == DRM_MODE_CONNECTOR_eDP)
@@ -1598,6 +1629,10 @@ radeon_add_atom_connector(struct drm_device *dev,
                case DRM_MODE_CONNECTOR_VGA:
                case DRM_MODE_CONNECTOR_DVIA:
                default:
+                       drm_connector_init(dev, &radeon_connector->base,
+                                          &radeon_dp_connector_funcs, connector_type);
+                       drm_connector_helper_add(&radeon_connector->base,
+                                                &radeon_dp_connector_helper_funcs);
                        connector->interlace_allowed = true;
                        connector->doublescan_allowed = true;
                        radeon_connector->dac_load_detect = true;
@@ -1610,6 +1645,10 @@ radeon_add_atom_connector(struct drm_device *dev,
                case DRM_MODE_CONNECTOR_HDMIA:
                case DRM_MODE_CONNECTOR_HDMIB:
                case DRM_MODE_CONNECTOR_DisplayPort:
+                       drm_connector_init(dev, &radeon_connector->base,
+                                          &radeon_dp_connector_funcs, connector_type);
+                       drm_connector_helper_add(&radeon_connector->base,
+                                                &radeon_dp_connector_helper_funcs);
                        drm_object_attach_property(&radeon_connector->base.base,
                                                      rdev->mode_info.underscan_property,
                                                      UNDERSCAN_OFF);
@@ -1619,6 +1658,9 @@ radeon_add_atom_connector(struct drm_device *dev,
                        drm_object_attach_property(&radeon_connector->base.base,
                                                      rdev->mode_info.underscan_vborder_property,
                                                      0);
+                       drm_object_attach_property(&radeon_connector->base.base,
+                                                  rdev->mode_info.audio_property,
+                                                  RADEON_AUDIO_DISABLE);
                        subpixel_order = SubPixelHorizontalRGB;
                        connector->interlace_allowed = true;
                        if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
@@ -1634,6 +1676,10 @@ radeon_add_atom_connector(struct drm_device *dev,
                        break;
                case DRM_MODE_CONNECTOR_LVDS:
                case DRM_MODE_CONNECTOR_eDP:
+                       drm_connector_init(dev, &radeon_connector->base,
+                                          &radeon_lvds_bridge_connector_funcs, connector_type);
+                       drm_connector_helper_add(&radeon_connector->base,
+                                                &radeon_dp_connector_helper_funcs);
                        drm_object_attach_property(&radeon_connector->base.base,
                                                      dev->mode_config.scaling_mode_property,
                                                      DRM_MODE_SCALE_FULLSCREEN);
@@ -1708,6 +1754,11 @@ radeon_add_atom_connector(struct drm_device *dev,
                                                              rdev->mode_info.underscan_vborder_property,
                                                              0);
                        }
+                       if (ASIC_IS_DCE2(rdev)) {
+                               drm_object_attach_property(&radeon_connector->base.base,
+                                                             rdev->mode_info.audio_property,
+                                                             RADEON_AUDIO_DISABLE);
+                       }
                        if (connector_type == DRM_MODE_CONNECTOR_DVII) {
                                radeon_connector->dac_load_detect = true;
                                drm_object_attach_property(&radeon_connector->base.base,
@@ -1748,6 +1799,11 @@ radeon_add_atom_connector(struct drm_device *dev,
                                                              rdev->mode_info.underscan_vborder_property,
                                                              0);
                        }
+                       if (ASIC_IS_DCE2(rdev)) {
+                               drm_object_attach_property(&radeon_connector->base.base,
+                                                             rdev->mode_info.audio_property,
+                                                             RADEON_AUDIO_DISABLE);
+                       }
                        subpixel_order = SubPixelHorizontalRGB;
                        connector->interlace_allowed = true;
                        if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
@@ -1787,6 +1843,11 @@ radeon_add_atom_connector(struct drm_device *dev,
                                                              rdev->mode_info.underscan_vborder_property,
                                                              0);
                        }
+                       if (ASIC_IS_DCE2(rdev)) {
+                               drm_object_attach_property(&radeon_connector->base.base,
+                                                             rdev->mode_info.audio_property,
+                                                             RADEON_AUDIO_DISABLE);
+                       }
                        connector->interlace_allowed = true;
                        /* in theory with a DP to VGA converter... */
                        connector->doublescan_allowed = false;
@@ -1797,7 +1858,7 @@ radeon_add_atom_connector(struct drm_device *dev,
                                goto failed;
                        radeon_dig_connector->igp_lane_info = igp_lane_info;
                        radeon_connector->con_priv = radeon_dig_connector;
-                       drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type);
+                       drm_connector_init(dev, &radeon_connector->base, &radeon_edp_connector_funcs, connector_type);
                        drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs);
                        if (i2c_bus->valid) {
                                /* add DP i2c bus */
index a560844103727dce62d2b8ef88290cd321a28936..66c222836631a4bc8dcd12b2f81f6e935218c566 100644 (file)
@@ -28,6 +28,7 @@
 #include <drm/radeon_drm.h>
 #include "radeon_reg.h"
 #include "radeon.h"
+#include "radeon_trace.h"
 
 static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
 {
@@ -80,10 +81,13 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
                p->relocs[i].lobj.bo = p->relocs[i].robj;
                p->relocs[i].lobj.written = !!r->write_domain;
 
-               /* the first reloc of an UVD job is the
-                  msg and that must be in VRAM */
-               if (p->ring == R600_RING_TYPE_UVD_INDEX && i == 0) {
-                       /* TODO: is this still needed for NI+ ? */
+               /* the first reloc of an UVD job is the msg and that must be in
+                  VRAM, also but everything into VRAM on AGP cards to avoid
+                  image corruptions */
+               if (p->ring == R600_RING_TYPE_UVD_INDEX &&
+                   p->rdev->family < CHIP_PALM &&
+                   (i == 0 || drm_pci_device_is_agp(p->rdev->ddev))) {
+
                        p->relocs[i].lobj.domain =
                                RADEON_GEM_DOMAIN_VRAM;
 
@@ -559,6 +563,8 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                return r;
        }
 
+       trace_radeon_cs(&parser);
+
        r = radeon_cs_ib_chunk(rdev, &parser);
        if (r) {
                goto out;
index 16cb8792b1e665f9048ec24f8c521eb052115662..841d0e09be3e9fb109b5afd45d012590a0ee6433 100644 (file)
@@ -1249,6 +1249,17 @@ int radeon_device_init(struct radeon_device *rdev,
        /* Registers mapping */
        /* TODO: block userspace mapping of io register */
        spin_lock_init(&rdev->mmio_idx_lock);
+       spin_lock_init(&rdev->smc_idx_lock);
+       spin_lock_init(&rdev->pll_idx_lock);
+       spin_lock_init(&rdev->mc_idx_lock);
+       spin_lock_init(&rdev->pcie_idx_lock);
+       spin_lock_init(&rdev->pciep_idx_lock);
+       spin_lock_init(&rdev->pif_idx_lock);
+       spin_lock_init(&rdev->cg_idx_lock);
+       spin_lock_init(&rdev->uvd_idx_lock);
+       spin_lock_init(&rdev->rcu_idx_lock);
+       spin_lock_init(&rdev->didt_idx_lock);
+       spin_lock_init(&rdev->end_idx_lock);
        if (rdev->family >= CHIP_BONAIRE) {
                rdev->rmmio_base = pci_resource_start(rdev->pdev, 5);
                rdev->rmmio_size = pci_resource_len(rdev->pdev, 5);
@@ -1309,13 +1320,22 @@ int radeon_device_init(struct radeon_device *rdev,
                        return r;
        }
        if ((radeon_testing & 1)) {
-               radeon_test_moves(rdev);
+               if (rdev->accel_working)
+                       radeon_test_moves(rdev);
+               else
+                       DRM_INFO("radeon: acceleration disabled, skipping move tests\n");
        }
        if ((radeon_testing & 2)) {
-               radeon_test_syncing(rdev);
+               if (rdev->accel_working)
+                       radeon_test_syncing(rdev);
+               else
+                       DRM_INFO("radeon: acceleration disabled, skipping sync tests\n");
        }
        if (radeon_benchmarking) {
-               radeon_benchmark(rdev, radeon_benchmarking);
+               if (rdev->accel_working)
+                       radeon_benchmark(rdev, radeon_benchmarking);
+               else
+                       DRM_INFO("radeon: acceleration disabled, skipping benchmarks\n");
        }
        return 0;
 }
index b055bddaa94c3d85e4b497721b8d239082c035a4..0d1aa050d41de7b02a1fd12065246c4239d817be 100644 (file)
@@ -1172,6 +1172,12 @@ static struct drm_prop_enum_list radeon_underscan_enum_list[] =
        { UNDERSCAN_AUTO, "auto" },
 };
 
+static struct drm_prop_enum_list radeon_audio_enum_list[] =
+{      { RADEON_AUDIO_DISABLE, "off" },
+       { RADEON_AUDIO_ENABLE, "on" },
+       { RADEON_AUDIO_AUTO, "auto" },
+};
+
 static int radeon_modeset_create_props(struct radeon_device *rdev)
 {
        int sz;
@@ -1222,6 +1228,12 @@ static int radeon_modeset_create_props(struct radeon_device *rdev)
        if (!rdev->mode_info.underscan_vborder_property)
                return -ENOMEM;
 
+       sz = ARRAY_SIZE(radeon_audio_enum_list);
+       rdev->mode_info.audio_property =
+               drm_property_create_enum(rdev->ddev, 0,
+                                        "audio",
+                                        radeon_audio_enum_list, sz);
+
        return 0;
 }
 
index cb4445f55a96c3aa10c703e868db1707b864170e..cdd12dcd988b1ed3260076b6d984cbf388dc35a7 100644 (file)
@@ -153,7 +153,7 @@ int radeon_benchmarking = 0;
 int radeon_testing = 0;
 int radeon_connector_table = 0;
 int radeon_tv = 1;
-int radeon_audio = 0;
+int radeon_audio = 1;
 int radeon_disp_priority = 0;
 int radeon_hw_i2c = 0;
 int radeon_pcie_gen2 = -1;
index d908d8d68f6ba73b77df6d7f98ba64f164f59412..ef63d3f00b2ffb3d212c46315d2f8226a1605f68 100644 (file)
@@ -247,6 +247,8 @@ struct radeon_mode_info {
        struct drm_property *underscan_property;
        struct drm_property *underscan_hborder_property;
        struct drm_property *underscan_vborder_property;
+       /* audio */
+       struct drm_property *audio_property;
        /* hardcoded DFP edid from BIOS */
        struct edid *bios_hardcoded_edid;
        int bios_hardcoded_edid_size;
@@ -471,6 +473,12 @@ struct radeon_router {
        u8 cd_mux_state;
 };
 
+enum radeon_connector_audio {
+       RADEON_AUDIO_DISABLE = 0,
+       RADEON_AUDIO_ENABLE = 1,
+       RADEON_AUDIO_AUTO = 2
+};
+
 struct radeon_connector {
        struct drm_connector base;
        uint32_t connector_id;
@@ -489,6 +497,7 @@ struct radeon_connector {
        struct radeon_hpd hpd;
        struct radeon_router router;
        struct radeon_i2c_chan *router_bus;
+       enum radeon_connector_audio audio;
 };
 
 struct radeon_framebuffer {
index d7555369a3e53101aa773309eff481a8f1f1c4ee..ac07ad1d4f8c903783acc26e3fc8f9f0e3449d44 100644 (file)
@@ -67,7 +67,16 @@ int radeon_pm_get_type_index(struct radeon_device *rdev,
 
 void radeon_pm_acpi_event_handler(struct radeon_device *rdev)
 {
-       if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
+       if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
+               mutex_lock(&rdev->pm.mutex);
+               if (power_supply_is_system_supplied() > 0)
+                       rdev->pm.dpm.ac_power = true;
+               else
+                       rdev->pm.dpm.ac_power = false;
+               if (rdev->asic->dpm.enable_bapm)
+                       radeon_dpm_enable_bapm(rdev, rdev->pm.dpm.ac_power);
+               mutex_unlock(&rdev->pm.mutex);
+        } else if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
                if (rdev->pm.profile == PM_PROFILE_AUTO) {
                        mutex_lock(&rdev->pm.mutex);
                        radeon_pm_update_profile(rdev);
@@ -333,7 +342,7 @@ static ssize_t radeon_get_pm_profile(struct device *dev,
                                     struct device_attribute *attr,
                                     char *buf)
 {
-       struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
+       struct drm_device *ddev = dev_get_drvdata(dev);
        struct radeon_device *rdev = ddev->dev_private;
        int cp = rdev->pm.profile;
 
@@ -349,7 +358,7 @@ static ssize_t radeon_set_pm_profile(struct device *dev,
                                     const char *buf,
                                     size_t count)
 {
-       struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
+       struct drm_device *ddev = dev_get_drvdata(dev);
        struct radeon_device *rdev = ddev->dev_private;
 
        mutex_lock(&rdev->pm.mutex);
@@ -383,7 +392,7 @@ static ssize_t radeon_get_pm_method(struct device *dev,
                                    struct device_attribute *attr,
                                    char *buf)
 {
-       struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
+       struct drm_device *ddev = dev_get_drvdata(dev);
        struct radeon_device *rdev = ddev->dev_private;
        int pm = rdev->pm.pm_method;
 
@@ -397,7 +406,7 @@ static ssize_t radeon_set_pm_method(struct device *dev,
                                    const char *buf,
                                    size_t count)
 {
-       struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
+       struct drm_device *ddev = dev_get_drvdata(dev);
        struct radeon_device *rdev = ddev->dev_private;
 
        /* we don't support the legacy modes with dpm */
@@ -433,7 +442,7 @@ static ssize_t radeon_get_dpm_state(struct device *dev,
                                    struct device_attribute *attr,
                                    char *buf)
 {
-       struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
+       struct drm_device *ddev = dev_get_drvdata(dev);
        struct radeon_device *rdev = ddev->dev_private;
        enum radeon_pm_state_type pm = rdev->pm.dpm.user_state;
 
@@ -447,7 +456,7 @@ static ssize_t radeon_set_dpm_state(struct device *dev,
                                    const char *buf,
                                    size_t count)
 {
-       struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
+       struct drm_device *ddev = dev_get_drvdata(dev);
        struct radeon_device *rdev = ddev->dev_private;
 
        mutex_lock(&rdev->pm.mutex);
@@ -472,7 +481,7 @@ static ssize_t radeon_get_dpm_forced_performance_level(struct device *dev,
                                                       struct device_attribute *attr,
                                                       char *buf)
 {
-       struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
+       struct drm_device *ddev = dev_get_drvdata(dev);
        struct radeon_device *rdev = ddev->dev_private;
        enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level;
 
@@ -486,7 +495,7 @@ static ssize_t radeon_set_dpm_forced_performance_level(struct device *dev,
                                                       const char *buf,
                                                       size_t count)
 {
-       struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
+       struct drm_device *ddev = dev_get_drvdata(dev);
        struct radeon_device *rdev = ddev->dev_private;
        enum radeon_dpm_forced_level level;
        int ret = 0;
@@ -524,7 +533,7 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev,
                                      struct device_attribute *attr,
                                      char *buf)
 {
-       struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev));
+       struct drm_device *ddev = dev_get_drvdata(dev);
        struct radeon_device *rdev = ddev->dev_private;
        int temp;
 
@@ -536,6 +545,23 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%d\n", temp);
 }
 
+static ssize_t radeon_hwmon_show_temp_thresh(struct device *dev,
+                                            struct device_attribute *attr,
+                                            char *buf)
+{
+       struct drm_device *ddev = dev_get_drvdata(dev);
+       struct radeon_device *rdev = ddev->dev_private;
+       int hyst = to_sensor_dev_attr(attr)->index;
+       int temp;
+
+       if (hyst)
+               temp = rdev->pm.dpm.thermal.min_temp;
+       else
+               temp = rdev->pm.dpm.thermal.max_temp;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", temp);
+}
+
 static ssize_t radeon_hwmon_show_name(struct device *dev,
                                      struct device_attribute *attr,
                                      char *buf)
@@ -544,16 +570,37 @@ static ssize_t radeon_hwmon_show_name(struct device *dev,
 }
 
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, radeon_hwmon_show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 1);
 static SENSOR_DEVICE_ATTR(name, S_IRUGO, radeon_hwmon_show_name, NULL, 0);
 
 static struct attribute *hwmon_attributes[] = {
        &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_temp1_crit.dev_attr.attr,
+       &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
        &sensor_dev_attr_name.dev_attr.attr,
        NULL
 };
 
+static umode_t hwmon_attributes_visible(struct kobject *kobj,
+                                       struct attribute *attr, int index)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct drm_device *ddev = dev_get_drvdata(dev);
+       struct radeon_device *rdev = ddev->dev_private;
+
+       /* Skip limit attributes if DPM is not enabled */
+       if (rdev->pm.pm_method != PM_METHOD_DPM &&
+           (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr ||
+            attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr))
+               return 0;
+
+       return attr->mode;
+}
+
 static const struct attribute_group hwmon_attrgroup = {
        .attrs = hwmon_attributes,
+       .is_visible = hwmon_attributes_visible,
 };
 
 static int radeon_hwmon_init(struct radeon_device *rdev)
@@ -870,10 +917,13 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
 
        radeon_dpm_post_set_power_state(rdev);
 
-       /* force low perf level for thermal */
-       if (rdev->pm.dpm.thermal_active &&
-           rdev->asic->dpm.force_performance_level) {
-               radeon_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_LOW);
+       if (rdev->asic->dpm.force_performance_level) {
+               if (rdev->pm.dpm.thermal_active)
+                       /* force low perf level for thermal */
+                       radeon_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_LOW);
+               else
+                       /* otherwise, enable auto */
+                       radeon_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO);
        }
 
 done:
@@ -952,7 +1002,7 @@ static void radeon_pm_resume_old(struct radeon_device *rdev)
 {
        /* set up the default clocks if the MC ucode is loaded */
        if ((rdev->family >= CHIP_BARTS) &&
-           (rdev->family <= CHIP_HAINAN) &&
+           (rdev->family <= CHIP_CAYMAN) &&
            rdev->mc_fw) {
                if (rdev->pm.default_vddc)
                        radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
@@ -996,7 +1046,7 @@ static void radeon_pm_resume_dpm(struct radeon_device *rdev)
        if (ret) {
                DRM_ERROR("radeon: dpm resume failed\n");
                if ((rdev->family >= CHIP_BARTS) &&
-                   (rdev->family <= CHIP_HAINAN) &&
+                   (rdev->family <= CHIP_CAYMAN) &&
                    rdev->mc_fw) {
                        if (rdev->pm.default_vddc)
                                radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
@@ -1047,7 +1097,7 @@ static int radeon_pm_init_old(struct radeon_device *rdev)
                radeon_pm_init_profile(rdev);
                /* set up the default clocks if the MC ucode is loaded */
                if ((rdev->family >= CHIP_BARTS) &&
-                   (rdev->family <= CHIP_HAINAN) &&
+                   (rdev->family <= CHIP_CAYMAN) &&
                    rdev->mc_fw) {
                        if (rdev->pm.default_vddc)
                                radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
@@ -1102,9 +1152,10 @@ static int radeon_pm_init_dpm(struct radeon_device *rdev)
 {
        int ret;
 
-       /* default to performance state */
+       /* default to balanced state */
        rdev->pm.dpm.state = POWER_STATE_TYPE_BALANCED;
        rdev->pm.dpm.user_state = POWER_STATE_TYPE_BALANCED;
+       rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO;
        rdev->pm.default_sclk = rdev->clock.default_sclk;
        rdev->pm.default_mclk = rdev->clock.default_mclk;
        rdev->pm.current_sclk = rdev->clock.default_sclk;
@@ -1132,7 +1183,7 @@ static int radeon_pm_init_dpm(struct radeon_device *rdev)
        if (ret) {
                rdev->pm.dpm_enabled = false;
                if ((rdev->family >= CHIP_BARTS) &&
-                   (rdev->family <= CHIP_HAINAN) &&
+                   (rdev->family <= CHIP_CAYMAN) &&
                    rdev->mc_fw) {
                        if (rdev->pm.default_vddc)
                                radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
index 46a25f037b843b70ebfb04e77ad55901111efd02..18254e1c3e718ee1c7c4cdd4321bf95b15581970 100644 (file)
@@ -839,9 +839,11 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data)
         * packet that is the root issue
         */
        i = (ring->rptr + ring->ptr_mask + 1 - 32) & ring->ptr_mask;
-       for (j = 0; j <= (count + 32); j++) {
-               seq_printf(m, "r[%5d]=0x%08x\n", i, ring->ring[i]);
-               i = (i + 1) & ring->ptr_mask;
+       if (ring->ready) {
+               for (j = 0; j <= (count + 32); j++) {
+                       seq_printf(m, "r[%5d]=0x%08x\n", i, ring->ring[i]);
+                       i = (i + 1) & ring->ptr_mask;
+               }
        }
        return 0;
 }
index eafd8160a15563c3aa762eabb6ea532aa766529a..f7e367815964f34756a13691935018ae95978ca1 100644 (file)
@@ -27,6 +27,26 @@ TRACE_EVENT(radeon_bo_create,
            TP_printk("bo=%p, pages=%u", __entry->bo, __entry->pages)
 );
 
+TRACE_EVENT(radeon_cs,
+           TP_PROTO(struct radeon_cs_parser *p),
+           TP_ARGS(p),
+           TP_STRUCT__entry(
+                            __field(u32, ring)
+                            __field(u32, dw)
+                            __field(u32, fences)
+                            ),
+
+           TP_fast_assign(
+                          __entry->ring = p->ring;
+                          __entry->dw = p->chunks[p->chunk_ib_idx].length_dw;
+                          __entry->fences = radeon_fence_count_emitted(
+                               p->rdev, p->ring);
+                          ),
+           TP_printk("ring=%u, dw=%u, fences=%u",
+                     __entry->ring, __entry->dw,
+                     __entry->fences)
+);
+
 DECLARE_EVENT_CLASS(radeon_fence_request,
 
            TP_PROTO(struct drm_device *dev, u32 seqno),
@@ -53,13 +73,6 @@ DEFINE_EVENT(radeon_fence_request, radeon_fence_emit,
            TP_ARGS(dev, seqno)
 );
 
-DEFINE_EVENT(radeon_fence_request, radeon_fence_retire,
-
-           TP_PROTO(struct drm_device *dev, u32 seqno),
-
-           TP_ARGS(dev, seqno)
-);
-
 DEFINE_EVENT(radeon_fence_request, radeon_fence_wait_begin,
 
            TP_PROTO(struct drm_device *dev, u32 seqno),
index 1a01bbff9bfa4f5c9ca1d354cd99abae981a36ce..a0f11856dddef7067871e630ed2bafcb9a2d4587 100644 (file)
@@ -476,8 +476,7 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
                return -EINVAL;
        }
 
-       /* TODO: is this still necessary on NI+ ? */
-       if ((cmd == 0 || cmd == 0x3) &&
+       if (p->rdev->family < CHIP_PALM && (cmd == 0 || cmd == 0x3) &&
            (start >> 28) != (p->rdev->uvd.gpu_addr >> 28)) {
                DRM_ERROR("msg/fb buffer %LX-%LX out of 256MB segment!\n",
                          start, end);
index b8074a8ec75a93c0566cfefa5ae5375041841e18..9566b5940a5ae723f90dfa11427e3f09bac233b3 100644 (file)
@@ -274,19 +274,26 @@ static void rs400_mc_init(struct radeon_device *rdev)
 
 uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg)
 {
+       unsigned long flags;
        uint32_t r;
 
+       spin_lock_irqsave(&rdev->mc_idx_lock, flags);
        WREG32(RS480_NB_MC_INDEX, reg & 0xff);
        r = RREG32(RS480_NB_MC_DATA);
        WREG32(RS480_NB_MC_INDEX, 0xff);
+       spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
        return r;
 }
 
 void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->mc_idx_lock, flags);
        WREG32(RS480_NB_MC_INDEX, ((reg) & 0xff) | RS480_NB_MC_IND_WR_EN);
        WREG32(RS480_NB_MC_DATA, (v));
        WREG32(RS480_NB_MC_INDEX, 0xff);
+       spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
 }
 
 #if defined(CONFIG_DEBUG_FS)
index 670b555d2ca229c3b39ac46cbbbf8e06e678f25b..6acba8017b9afd24d63b906a2fb9b8ec5934ec1f 100644 (file)
@@ -847,16 +847,26 @@ void rs600_bandwidth_update(struct radeon_device *rdev)
 
 uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg)
 {
+       unsigned long flags;
+       u32 r;
+
+       spin_lock_irqsave(&rdev->mc_idx_lock, flags);
        WREG32(R_000070_MC_IND_INDEX, S_000070_MC_IND_ADDR(reg) |
                S_000070_MC_IND_CITF_ARB0(1));
-       return RREG32(R_000074_MC_IND_DATA);
+       r = RREG32(R_000074_MC_IND_DATA);
+       spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
+       return r;
 }
 
 void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->mc_idx_lock, flags);
        WREG32(R_000070_MC_IND_INDEX, S_000070_MC_IND_ADDR(reg) |
                S_000070_MC_IND_CITF_ARB0(1) | S_000070_MC_IND_WR_EN(1));
        WREG32(R_000074_MC_IND_DATA, v);
+       spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
 }
 
 static void rs600_debugfs(struct radeon_device *rdev)
index d8ddfb34545de8dce3fb55f2315ce4121a4bab8e..1447d794c22ad21648408a390e4b78bc84493af0 100644 (file)
@@ -631,20 +631,27 @@ void rs690_bandwidth_update(struct radeon_device *rdev)
 
 uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg)
 {
+       unsigned long flags;
        uint32_t r;
 
+       spin_lock_irqsave(&rdev->mc_idx_lock, flags);
        WREG32(R_000078_MC_INDEX, S_000078_MC_IND_ADDR(reg));
        r = RREG32(R_00007C_MC_DATA);
        WREG32(R_000078_MC_INDEX, ~C_000078_MC_IND_ADDR);
+       spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
        return r;
 }
 
 void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->mc_idx_lock, flags);
        WREG32(R_000078_MC_INDEX, S_000078_MC_IND_ADDR(reg) |
                S_000078_MC_IND_WR_EN(1));
        WREG32(R_00007C_MC_DATA, v);
        WREG32(R_000078_MC_INDEX, 0x7F);
+       spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
 }
 
 static void rs690_mc_program(struct radeon_device *rdev)
index d1a1ce73bd45548392deabbef5815e463a97dcd2..6af8505cf4d2db624ee64811ba4575158d90e974 100644 (file)
@@ -62,9 +62,7 @@ static void rs780_get_pm_mode_parameters(struct radeon_device *rdev)
                        radeon_crtc = to_radeon_crtc(crtc);
                        pi->crtc_id = radeon_crtc->crtc_id;
                        if (crtc->mode.htotal && crtc->mode.vtotal)
-                               pi->refresh_rate =
-                                       (crtc->mode.clock * 1000) /
-                                       (crtc->mode.htotal * crtc->mode.vtotal);
+                               pi->refresh_rate = drm_mode_vrefresh(&crtc->mode);
                        break;
                }
        }
@@ -376,9 +374,8 @@ static void rs780_disable_vbios_powersaving(struct radeon_device *rdev)
        WREG32_P(CG_INTGFX_MISC, 0, ~0xFFF00000);
 }
 
-static void rs780_force_voltage_to_high(struct radeon_device *rdev)
+static void rs780_force_voltage(struct radeon_device *rdev, u16 voltage)
 {
-       struct igp_power_info *pi = rs780_get_pi(rdev);
        struct igp_ps *current_state = rs780_get_ps(rdev->pm.dpm.current_ps);
 
        if ((current_state->max_voltage == RS780_VDDC_LEVEL_HIGH) &&
@@ -390,7 +387,7 @@ static void rs780_force_voltage_to_high(struct radeon_device *rdev)
        udelay(1);
 
        WREG32_P(FVTHROT_PWM_CTRL_REG0,
-                STARTING_PWM_HIGHTIME(pi->max_voltage),
+                STARTING_PWM_HIGHTIME(voltage),
                 ~STARTING_PWM_HIGHTIME_MASK);
 
        WREG32_P(FVTHROT_PWM_CTRL_REG0,
@@ -404,6 +401,26 @@ static void rs780_force_voltage_to_high(struct radeon_device *rdev)
        WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~SPLL_BYPASS_CNTL);
 }
 
+static void rs780_force_fbdiv(struct radeon_device *rdev, u32 fb_div)
+{
+       struct igp_ps *current_state = rs780_get_ps(rdev->pm.dpm.current_ps);
+
+       if (current_state->sclk_low == current_state->sclk_high)
+               return;
+
+       WREG32_P(GFX_MACRO_BYPASS_CNTL, SPLL_BYPASS_CNTL, ~SPLL_BYPASS_CNTL);
+
+       WREG32_P(FVTHROT_FBDIV_REG2, FORCED_FEEDBACK_DIV(fb_div),
+                ~FORCED_FEEDBACK_DIV_MASK);
+       WREG32_P(FVTHROT_FBDIV_REG1, STARTING_FEEDBACK_DIV(fb_div),
+                ~STARTING_FEEDBACK_DIV_MASK);
+       WREG32_P(FVTHROT_FBDIV_REG1, FORCE_FEEDBACK_DIV, ~FORCE_FEEDBACK_DIV);
+
+       udelay(100);
+
+       WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~SPLL_BYPASS_CNTL);
+}
+
 static int rs780_set_engine_clock_scaling(struct radeon_device *rdev,
                                          struct radeon_ps *new_ps,
                                          struct radeon_ps *old_ps)
@@ -432,17 +449,13 @@ static int rs780_set_engine_clock_scaling(struct radeon_device *rdev,
        if (ret)
                return ret;
 
-       WREG32_P(GFX_MACRO_BYPASS_CNTL, SPLL_BYPASS_CNTL, ~SPLL_BYPASS_CNTL);
-
-       WREG32_P(FVTHROT_FBDIV_REG2, FORCED_FEEDBACK_DIV(max_dividers.fb_div),
-                ~FORCED_FEEDBACK_DIV_MASK);
-       WREG32_P(FVTHROT_FBDIV_REG1, STARTING_FEEDBACK_DIV(max_dividers.fb_div),
-                ~STARTING_FEEDBACK_DIV_MASK);
-       WREG32_P(FVTHROT_FBDIV_REG1, FORCE_FEEDBACK_DIV, ~FORCE_FEEDBACK_DIV);
-
-       udelay(100);
+       if ((min_dividers.ref_div != max_dividers.ref_div) ||
+           (min_dividers.post_div != max_dividers.post_div) ||
+           (max_dividers.ref_div != current_max_dividers.ref_div) ||
+           (max_dividers.post_div != current_max_dividers.post_div))
+               return -EINVAL;
 
-       WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~SPLL_BYPASS_CNTL);
+       rs780_force_fbdiv(rdev, max_dividers.fb_div);
 
        if (max_dividers.fb_div > min_dividers.fb_div) {
                WREG32_P(FVTHROT_FBDIV_REG0,
@@ -486,6 +499,9 @@ static void rs780_activate_engine_clk_scaling(struct radeon_device *rdev,
            (new_state->sclk_low == old_state->sclk_low))
                return;
 
+       if (new_state->sclk_high == new_state->sclk_low)
+               return;
+
        rs780_clk_scaling_enable(rdev, true);
 }
 
@@ -649,7 +665,7 @@ int rs780_dpm_set_power_state(struct radeon_device *rdev)
        rs780_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
 
        if (pi->voltage_control) {
-               rs780_force_voltage_to_high(rdev);
+               rs780_force_voltage(rdev, pi->max_voltage);
                mdelay(5);
        }
 
@@ -717,14 +733,18 @@ static void rs780_parse_pplib_non_clock_info(struct radeon_device *rdev,
        if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
                rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
                rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
-       } else if (r600_is_uvd_state(rps->class, rps->class2)) {
-               rps->vclk = RS780_DEFAULT_VCLK_FREQ;
-               rps->dclk = RS780_DEFAULT_DCLK_FREQ;
        } else {
                rps->vclk = 0;
                rps->dclk = 0;
        }
 
+       if (r600_is_uvd_state(rps->class, rps->class2)) {
+               if ((rps->vclk == 0) || (rps->dclk == 0)) {
+                       rps->vclk = RS780_DEFAULT_VCLK_FREQ;
+                       rps->dclk = RS780_DEFAULT_DCLK_FREQ;
+               }
+       }
+
        if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT)
                rdev->pm.dpm.boot_ps = rps;
        if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
@@ -986,3 +1006,55 @@ void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rde
                seq_printf(m, "power level 1    sclk: %u vddc_index: %d\n",
                           ps->sclk_high, ps->max_voltage);
 }
+
+int rs780_dpm_force_performance_level(struct radeon_device *rdev,
+                                     enum radeon_dpm_forced_level level)
+{
+       struct igp_power_info *pi = rs780_get_pi(rdev);
+       struct radeon_ps *rps = rdev->pm.dpm.current_ps;
+       struct igp_ps *ps = rs780_get_ps(rps);
+       struct atom_clock_dividers dividers;
+       int ret;
+
+       rs780_clk_scaling_enable(rdev, false);
+       rs780_voltage_scaling_enable(rdev, false);
+
+       if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
+               if (pi->voltage_control)
+                       rs780_force_voltage(rdev, pi->max_voltage);
+
+               ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
+                                                    ps->sclk_high, false, &dividers);
+               if (ret)
+                       return ret;
+
+               rs780_force_fbdiv(rdev, dividers.fb_div);
+       } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
+               ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
+                                                    ps->sclk_low, false, &dividers);
+               if (ret)
+                       return ret;
+
+               rs780_force_fbdiv(rdev, dividers.fb_div);
+
+               if (pi->voltage_control)
+                       rs780_force_voltage(rdev, pi->min_voltage);
+       } else {
+               if (pi->voltage_control)
+                       rs780_force_voltage(rdev, pi->max_voltage);
+
+               if (ps->sclk_high != ps->sclk_low) {
+                       WREG32_P(FVTHROT_FBDIV_REG1, 0, ~FORCE_FEEDBACK_DIV);
+                       rs780_clk_scaling_enable(rdev, true);
+               }
+
+               if (pi->voltage_control) {
+                       rs780_voltage_scaling_enable(rdev, true);
+                       rs780_enable_voltage_scaling(rdev, rps);
+               }
+       }
+
+       rdev->pm.dpm.forced_level = level;
+
+       return 0;
+}
index 8ea1573ae820ef62202a30c680f6540fec127cec..873eb4b193b4f86c35fa2cc02417adbdee54344d 100644 (file)
@@ -209,19 +209,27 @@ static void rv515_mc_init(struct radeon_device *rdev)
 
 uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg)
 {
+       unsigned long flags;
        uint32_t r;
 
+       spin_lock_irqsave(&rdev->mc_idx_lock, flags);
        WREG32(MC_IND_INDEX, 0x7f0000 | (reg & 0xffff));
        r = RREG32(MC_IND_DATA);
        WREG32(MC_IND_INDEX, 0);
+       spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
+
        return r;
 }
 
 void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&rdev->mc_idx_lock, flags);
        WREG32(MC_IND_INDEX, 0xff0000 | ((reg) & 0xffff));
        WREG32(MC_IND_DATA, (v));
        WREG32(MC_IND_INDEX, 0);
+       spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
 }
 
 #if defined(CONFIG_DEBUG_FS)
index ab1f2016f21e44461e42892440df17b695b17f09..5811d277a36a60ec845cbcadf9588326a01a488b 100644 (file)
@@ -1758,8 +1758,6 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev)
 
        rv6xx_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
 
-       rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO;
-
        return 0;
 }
 
index 8cbb85dae5aa38500ac5803754ffcf94af613593..913b025ae9b399695bed47af97cccf08fe68caf7 100644 (file)
@@ -2064,12 +2064,6 @@ int rv770_dpm_set_power_state(struct radeon_device *rdev)
                rv770_program_dcodt_after_state_switch(rdev, new_ps, old_ps);
        rv770_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
 
-       ret = rv770_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO);
-       if (ret) {
-               DRM_ERROR("rv770_dpm_force_performance_level failed\n");
-               return ret;
-       }
-
        return 0;
 }
 
@@ -2147,14 +2141,18 @@ static void rv7xx_parse_pplib_non_clock_info(struct radeon_device *rdev,
        if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
                rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
                rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
-       } else if (r600_is_uvd_state(rps->class, rps->class2)) {
-               rps->vclk = RV770_DEFAULT_VCLK_FREQ;
-               rps->dclk = RV770_DEFAULT_DCLK_FREQ;
        } else {
                rps->vclk = 0;
                rps->dclk = 0;
        }
 
+       if (r600_is_uvd_state(rps->class, rps->class2)) {
+               if ((rps->vclk == 0) || (rps->dclk == 0)) {
+                       rps->vclk = RV770_DEFAULT_VCLK_FREQ;
+                       rps->dclk = RV770_DEFAULT_DCLK_FREQ;
+               }
+       }
+
        if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT)
                rdev->pm.dpm.boot_ps = rps;
        if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
index ab95da570215b7c68895be5bbe7765dd92ea758a..b2a224407365da6750572c30309466c025fb57ee 100644 (file)
@@ -274,8 +274,8 @@ static const u8 cayman_smc_int_vectors[] =
        0x08, 0x72, 0x08, 0x72
 };
 
-int rv770_set_smc_sram_address(struct radeon_device *rdev,
-                              u16 smc_address, u16 limit)
+static int rv770_set_smc_sram_address(struct radeon_device *rdev,
+                                     u16 smc_address, u16 limit)
 {
        u32 addr;
 
@@ -296,9 +296,10 @@ int rv770_copy_bytes_to_smc(struct radeon_device *rdev,
                            u16 smc_start_address, const u8 *src,
                            u16 byte_count, u16 limit)
 {
+       unsigned long flags;
        u32 data, original_data, extra_shift;
        u16 addr;
-       int ret;
+       int ret = 0;
 
        if (smc_start_address & 3)
                return -EINVAL;
@@ -307,13 +308,14 @@ int rv770_copy_bytes_to_smc(struct radeon_device *rdev,
 
        addr = smc_start_address;
 
+       spin_lock_irqsave(&rdev->smc_idx_lock, flags);
        while (byte_count >= 4) {
                /* SMC address space is BE */
                data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
 
                ret = rv770_set_smc_sram_address(rdev, addr, limit);
                if (ret)
-                       return ret;
+                       goto done;
 
                WREG32(SMC_SRAM_DATA, data);
 
@@ -328,7 +330,7 @@ int rv770_copy_bytes_to_smc(struct radeon_device *rdev,
 
                ret = rv770_set_smc_sram_address(rdev, addr, limit);
                if (ret)
-                       return ret;
+                       goto done;
 
                original_data = RREG32(SMC_SRAM_DATA);
 
@@ -346,12 +348,15 @@ int rv770_copy_bytes_to_smc(struct radeon_device *rdev,
 
                ret = rv770_set_smc_sram_address(rdev, addr, limit);
                if (ret)
-                       return ret;
+                       goto done;
 
                WREG32(SMC_SRAM_DATA, data);
        }
 
-       return 0;
+done:
+       spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
+
+       return ret;
 }
 
 static int rv770_program_interrupt_vectors(struct radeon_device *rdev,
@@ -461,12 +466,15 @@ PPSMC_Result rv770_wait_for_smc_inactive(struct radeon_device *rdev)
 
 static void rv770_clear_smc_sram(struct radeon_device *rdev, u16 limit)
 {
+       unsigned long flags;
        u16 i;
 
+       spin_lock_irqsave(&rdev->smc_idx_lock, flags);
        for (i = 0;  i < limit; i += 4) {
                rv770_set_smc_sram_address(rdev, i, limit);
                WREG32(SMC_SRAM_DATA, 0);
        }
+       spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
 }
 
 int rv770_load_smc_ucode(struct radeon_device *rdev,
@@ -595,27 +603,29 @@ int rv770_load_smc_ucode(struct radeon_device *rdev,
 int rv770_read_smc_sram_dword(struct radeon_device *rdev,
                              u16 smc_address, u32 *value, u16 limit)
 {
+       unsigned long flags;
        int ret;
 
+       spin_lock_irqsave(&rdev->smc_idx_lock, flags);
        ret = rv770_set_smc_sram_address(rdev, smc_address, limit);
-       if (ret)
-               return ret;
-
-       *value = RREG32(SMC_SRAM_DATA);
+       if (ret == 0)
+               *value = RREG32(SMC_SRAM_DATA);
+       spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
 
-       return 0;
+       return ret;
 }
 
 int rv770_write_smc_sram_dword(struct radeon_device *rdev,
                               u16 smc_address, u32 value, u16 limit)
 {
+       unsigned long flags;
        int ret;
 
+       spin_lock_irqsave(&rdev->smc_idx_lock, flags);
        ret = rv770_set_smc_sram_address(rdev, smc_address, limit);
-       if (ret)
-               return ret;
+       if (ret == 0)
+               WREG32(SMC_SRAM_DATA, value);
+       spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
 
-       WREG32(SMC_SRAM_DATA, value);
-
-       return 0;
+       return ret;
 }
index f78d92a4b3259b4d779b8a448ba02f412fd1d41b..3b2c963c4880048646d6b80bf80ade153f505db3 100644 (file)
@@ -187,8 +187,6 @@ typedef struct RV770_SMC_STATETABLE RV770_SMC_STATETABLE;
 #define RV770_SMC_SOFT_REGISTER_uvd_enabled             0x9C
 #define RV770_SMC_SOFT_REGISTER_is_asic_lombok          0xA0
 
-int rv770_set_smc_sram_address(struct radeon_device *rdev,
-                              u16 smc_address, u16 limit);
 int rv770_copy_bytes_to_smc(struct radeon_device *rdev,
                            u16 smc_start_address, const u8 *src,
                            u16 byte_count, u16 limit);
index 9fe60e5429223c6cb5688af3ca50225d4570aa67..1ae277152cc7f0c66f7babbcb0cdfcec5ab04f71 100644 (file)
 #define AFMT_VBI_PACKET_CONTROL              0x7608
 #       define AFMT_GENERIC0_UPDATE          (1 << 2)
 #define AFMT_INFOFRAME_CONTROL0              0x760c
-#       define AFMT_AUDIO_INFO_SOURCE        (1 << 6) /* 0 - sound block; 1 - hmdi regs */
+#       define AFMT_AUDIO_INFO_SOURCE        (1 << 6) /* 0 - sound block; 1 - hdmi regs */
 #       define AFMT_AUDIO_INFO_UPDATE        (1 << 7)
 #       define AFMT_MPEG_INFO_UPDATE         (1 << 10)
 #define AFMT_GENERIC0_7                      0x7610
index 3e23b757dcfa578859d7ff5d96b04a9c7ed85691..c354c1094967990a46caea46612caed123bc9b51 100644 (file)
@@ -83,6 +83,8 @@ extern void si_dma_vm_set_page(struct radeon_device *rdev,
                               uint64_t pe,
                               uint64_t addr, unsigned count,
                               uint32_t incr, uint32_t flags);
+static void si_enable_gui_idle_interrupt(struct radeon_device *rdev,
+                                        bool enable);
 
 static const u32 verde_rlc_save_restore_register_list[] =
 {
@@ -3386,6 +3388,8 @@ static int si_cp_resume(struct radeon_device *rdev)
        u32 rb_bufsz;
        int r;
 
+       si_enable_gui_idle_interrupt(rdev, false);
+
        WREG32(CP_SEM_WAIT_TIMER, 0x0);
        WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
 
@@ -3501,6 +3505,8 @@ static int si_cp_resume(struct radeon_device *rdev)
                rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false;
        }
 
+       si_enable_gui_idle_interrupt(rdev, true);
+
        return 0;
 }
 
@@ -4888,7 +4894,7 @@ static void si_enable_gfx_cgpg(struct radeon_device *rdev,
 {
        u32 tmp;
 
-       if (enable && (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG)) {
+       if (enable && (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG)) {
                tmp = RLC_PUD(0x10) | RLC_PDD(0x10) | RLC_TTPD(0x10) | RLC_MSD(0x10);
                WREG32(RLC_TTOP_D, tmp);
 
@@ -5250,6 +5256,7 @@ void si_update_cg(struct radeon_device *rdev,
                  u32 block, bool enable)
 {
        if (block & RADEON_CG_BLOCK_GFX) {
+               si_enable_gui_idle_interrupt(rdev, false);
                /* order matters! */
                if (enable) {
                        si_enable_mgcg(rdev, true);
@@ -5258,6 +5265,7 @@ void si_update_cg(struct radeon_device *rdev,
                        si_enable_cgcg(rdev, false);
                        si_enable_mgcg(rdev, false);
                }
+               si_enable_gui_idle_interrupt(rdev, true);
        }
 
        if (block & RADEON_CG_BLOCK_MC) {
@@ -5408,7 +5416,7 @@ static void si_init_pg(struct radeon_device *rdev)
                        si_init_dma_pg(rdev);
                }
                si_init_ao_cu_mask(rdev);
-               if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG) {
+               if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG) {
                        si_init_gfx_cgpg(rdev);
                }
                si_enable_dma_pg(rdev, true);
@@ -5560,7 +5568,9 @@ static void si_disable_interrupt_state(struct radeon_device *rdev)
 {
        u32 tmp;
 
-       WREG32(CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
+       tmp = RREG32(CP_INT_CNTL_RING0) &
+               (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
+       WREG32(CP_INT_CNTL_RING0, tmp);
        WREG32(CP_INT_CNTL_RING1, 0);
        WREG32(CP_INT_CNTL_RING2, 0);
        tmp = RREG32(DMA_CNTL + DMA0_REGISTER_OFFSET) & ~TRAP_ENABLE;
@@ -5685,7 +5695,7 @@ static int si_irq_init(struct radeon_device *rdev)
 
 int si_irq_set(struct radeon_device *rdev)
 {
-       u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE;
+       u32 cp_int_cntl;
        u32 cp_int_cntl1 = 0, cp_int_cntl2 = 0;
        u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0;
        u32 hpd1 = 0, hpd2 = 0, hpd3 = 0, hpd4 = 0, hpd5 = 0, hpd6 = 0;
@@ -5706,6 +5716,9 @@ int si_irq_set(struct radeon_device *rdev)
                return 0;
        }
 
+       cp_int_cntl = RREG32(CP_INT_CNTL_RING0) &
+               (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
+
        if (!ASIC_IS_NODCE(rdev)) {
                hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
                hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN;
index 5be9b4e723507ea1992df820b96aef9fec8de5b9..9ace28702c761a196089c7e88442e45b08a3ed16 100644 (file)
@@ -2910,6 +2910,7 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
        bool disable_sclk_switching = false;
        u32 mclk, sclk;
        u16 vddc, vddci;
+       u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;
        int i;
 
        if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
@@ -2943,6 +2944,29 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
                }
        }
 
+       /* limit clocks to max supported clocks based on voltage dependency tables */
+       btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
+                                                       &max_sclk_vddc);
+       btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
+                                                       &max_mclk_vddci);
+       btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
+                                                       &max_mclk_vddc);
+
+       for (i = 0; i < ps->performance_level_count; i++) {
+               if (max_sclk_vddc) {
+                       if (ps->performance_levels[i].sclk > max_sclk_vddc)
+                               ps->performance_levels[i].sclk = max_sclk_vddc;
+               }
+               if (max_mclk_vddci) {
+                       if (ps->performance_levels[i].mclk > max_mclk_vddci)
+                               ps->performance_levels[i].mclk = max_mclk_vddci;
+               }
+               if (max_mclk_vddc) {
+                       if (ps->performance_levels[i].mclk > max_mclk_vddc)
+                               ps->performance_levels[i].mclk = max_mclk_vddc;
+               }
+       }
+
        /* XXX validate the min clocks required for display */
 
        if (disable_mclk_switching) {
@@ -6075,12 +6099,6 @@ int si_dpm_set_power_state(struct radeon_device *rdev)
                return ret;
        }
 
-       ret = si_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO);
-       if (ret) {
-               DRM_ERROR("si_dpm_force_performance_level failed\n");
-               return ret;
-       }
-
        si_update_cg(rdev, (RADEON_CG_BLOCK_GFX |
                            RADEON_CG_BLOCK_MC |
                            RADEON_CG_BLOCK_SDMA |
index 5f524c0a541e453b3b882375ca2febeddf18c867..d422a1cbf727b375c467bcf78dc417431c7db2fd 100644 (file)
@@ -29,8 +29,8 @@
 #include "ppsmc.h"
 #include "radeon_ucode.h"
 
-int si_set_smc_sram_address(struct radeon_device *rdev,
-                           u32 smc_address, u32 limit)
+static int si_set_smc_sram_address(struct radeon_device *rdev,
+                                  u32 smc_address, u32 limit)
 {
        if (smc_address & 3)
                return -EINVAL;
@@ -47,7 +47,8 @@ int si_copy_bytes_to_smc(struct radeon_device *rdev,
                         u32 smc_start_address,
                         const u8 *src, u32 byte_count, u32 limit)
 {
-       int ret;
+       unsigned long flags;
+       int ret = 0;
        u32 data, original_data, addr, extra_shift;
 
        if (smc_start_address & 3)
@@ -57,13 +58,14 @@ int si_copy_bytes_to_smc(struct radeon_device *rdev,
 
        addr = smc_start_address;
 
+       spin_lock_irqsave(&rdev->smc_idx_lock, flags);
        while (byte_count >= 4) {
                /* SMC address space is BE */
                data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
 
                ret = si_set_smc_sram_address(rdev, addr, limit);
                if (ret)
-                       return ret;
+                       goto done;
 
                WREG32(SMC_IND_DATA_0, data);
 
@@ -78,7 +80,7 @@ int si_copy_bytes_to_smc(struct radeon_device *rdev,
 
                ret = si_set_smc_sram_address(rdev, addr, limit);
                if (ret)
-                       return ret;
+                       goto done;
 
                original_data = RREG32(SMC_IND_DATA_0);
 
@@ -96,11 +98,15 @@ int si_copy_bytes_to_smc(struct radeon_device *rdev,
 
                ret = si_set_smc_sram_address(rdev, addr, limit);
                if (ret)
-                       return ret;
+                       goto done;
 
                WREG32(SMC_IND_DATA_0, data);
        }
-       return 0;
+
+done:
+       spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
+
+       return ret;
 }
 
 void si_start_smc(struct radeon_device *rdev)
@@ -203,6 +209,7 @@ PPSMC_Result si_wait_for_smc_inactive(struct radeon_device *rdev)
 
 int si_load_smc_ucode(struct radeon_device *rdev, u32 limit)
 {
+       unsigned long flags;
        u32 ucode_start_address;
        u32 ucode_size;
        const u8 *src;
@@ -241,6 +248,7 @@ int si_load_smc_ucode(struct radeon_device *rdev, u32 limit)
                return -EINVAL;
 
        src = (const u8 *)rdev->smc_fw->data;
+       spin_lock_irqsave(&rdev->smc_idx_lock, flags);
        WREG32(SMC_IND_INDEX_0, ucode_start_address);
        WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0);
        while (ucode_size >= 4) {
@@ -253,6 +261,7 @@ int si_load_smc_ucode(struct radeon_device *rdev, u32 limit)
                ucode_size -= 4;
        }
        WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0);
+       spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
 
        return 0;
 }
@@ -260,25 +269,29 @@ int si_load_smc_ucode(struct radeon_device *rdev, u32 limit)
 int si_read_smc_sram_dword(struct radeon_device *rdev, u32 smc_address,
                           u32 *value, u32 limit)
 {
+       unsigned long flags;
        int ret;
 
+       spin_lock_irqsave(&rdev->smc_idx_lock, flags);
        ret = si_set_smc_sram_address(rdev, smc_address, limit);
-       if (ret)
-               return ret;
+       if (ret == 0)
+               *value = RREG32(SMC_IND_DATA_0);
+       spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
 
-       *value = RREG32(SMC_IND_DATA_0);
-       return 0;
+       return ret;
 }
 
 int si_write_smc_sram_dword(struct radeon_device *rdev, u32 smc_address,
                            u32 value, u32 limit)
 {
+       unsigned long flags;
        int ret;
 
+       spin_lock_irqsave(&rdev->smc_idx_lock, flags);
        ret = si_set_smc_sram_address(rdev, smc_address, limit);
-       if (ret)
-               return ret;
+       if (ret == 0)
+               WREG32(SMC_IND_DATA_0, value);
+       spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
 
-       WREG32(SMC_IND_DATA_0, value);
-       return 0;
+       return ret;
 }
index 864761c0120ecfaa5239d31fd9b06b278ad7d76c..96ea6db8bf575e7a45f6af501e26120f7e996a9a 100644 (file)
@@ -1319,8 +1319,6 @@ int sumo_dpm_set_power_state(struct radeon_device *rdev)
        if (pi->enable_dpm)
                sumo_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
 
-       rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO;
-
        return 0;
 }
 
index b07b7b8f1aff4523bfe955a0beddbc041efb9164..7f998bf1cc9dd796b412dae45184dc5f1c76f184 100644 (file)
@@ -1068,6 +1068,17 @@ static void trinity_update_requested_ps(struct radeon_device *rdev,
        pi->requested_rps.ps_priv = &pi->requested_ps;
 }
 
+void trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable)
+{
+       struct trinity_power_info *pi = trinity_get_pi(rdev);
+
+       if (pi->enable_bapm) {
+               trinity_acquire_mutex(rdev);
+               trinity_dpm_bapm_enable(rdev, enable);
+               trinity_release_mutex(rdev);
+       }
+}
+
 int trinity_dpm_enable(struct radeon_device *rdev)
 {
        struct trinity_power_info *pi = trinity_get_pi(rdev);
@@ -1091,6 +1102,7 @@ int trinity_dpm_enable(struct radeon_device *rdev)
        trinity_program_sclk_dpm(rdev);
        trinity_start_dpm(rdev);
        trinity_wait_for_dpm_enabled(rdev);
+       trinity_dpm_bapm_enable(rdev, false);
        trinity_release_mutex(rdev);
 
        if (rdev->irq.installed &&
@@ -1116,6 +1128,7 @@ void trinity_dpm_disable(struct radeon_device *rdev)
                trinity_release_mutex(rdev);
                return;
        }
+       trinity_dpm_bapm_enable(rdev, false);
        trinity_disable_clock_power_gating(rdev);
        sumo_clear_vc(rdev);
        trinity_wait_for_level_0(rdev);
@@ -1212,6 +1225,8 @@ int trinity_dpm_set_power_state(struct radeon_device *rdev)
 
        trinity_acquire_mutex(rdev);
        if (pi->enable_dpm) {
+               if (pi->enable_bapm)
+                       trinity_dpm_bapm_enable(rdev, rdev->pm.dpm.ac_power);
                trinity_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
                trinity_enable_power_level_0(rdev);
                trinity_force_level_0(rdev);
@@ -1221,7 +1236,6 @@ int trinity_dpm_set_power_state(struct radeon_device *rdev)
                trinity_force_level_0(rdev);
                trinity_unforce_levels(rdev);
                trinity_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
-               rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO;
        }
        trinity_release_mutex(rdev);
 
@@ -1854,6 +1868,7 @@ int trinity_dpm_init(struct radeon_device *rdev)
        for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++)
                pi->at[i] = TRINITY_AT_DFLT;
 
+       pi->enable_bapm = true;
        pi->enable_nbps_policy = true;
        pi->enable_sclk_ds = true;
        pi->enable_gfx_power_gating = true;
index e82df071f8b3e5e6f64265f150aa3c1fffb90b5a..c261657750cacd791876db78b1bea618cced24ac 100644 (file)
@@ -108,6 +108,7 @@ struct trinity_power_info {
        bool enable_auto_thermal_throttling;
        bool enable_dpm;
        bool enable_sclk_ds;
+       bool enable_bapm;
        bool uvd_dpm;
        struct radeon_ps current_rps;
        struct trinity_ps current_ps;
@@ -118,6 +119,7 @@ struct trinity_power_info {
 #define TRINITY_AT_DFLT            30
 
 /* trinity_smc.c */
+int trinity_dpm_bapm_enable(struct radeon_device *rdev, bool enable);
 int trinity_dpm_config(struct radeon_device *rdev, bool enable);
 int trinity_uvd_dpm_config(struct radeon_device *rdev);
 int trinity_dpm_force_state(struct radeon_device *rdev, u32 n);
index a42d89f1830cce2ae6611163601755c9de5243d6..9672bcbc7312218a357f07ae54393ed511284279 100644 (file)
@@ -56,6 +56,14 @@ static int trinity_notify_message_to_smu(struct radeon_device *rdev, u32 id)
        return 0;
 }
 
+int trinity_dpm_bapm_enable(struct radeon_device *rdev, bool enable)
+{
+       if (enable)
+               return trinity_notify_message_to_smu(rdev, PPSMC_MSG_EnableBAPM);
+       else
+               return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DisableBAPM);
+}
+
 int trinity_dpm_config(struct radeon_device *rdev, bool enable)
 {
        if (enable)
index 7266805d9786c6fe9bfd38501f7ab674f7d05a73..3100fa9cb52f4ff5f0b924af6d146f1e06ae6908 100644 (file)
@@ -212,8 +212,8 @@ int uvd_v1_0_start(struct radeon_device *rdev)
        /* enable VCPU clock */
        WREG32(UVD_VCPU_CNTL,  1 << 9);
 
-       /* enable UMC */
-       WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
+       /* enable UMC and NC0 */
+       WREG32_P(UVD_LMI_CTRL2, 1 << 13, ~((1 << 8) | (1 << 13)));
 
        /* boot up the VCPU */
        WREG32(UVD_SOFT_RESET, 0);
index 58a5f3261c0b083f026087f8722bf6e6915ea25f..a868176c258a95aee788253038637b83ec54a78f 100644 (file)
@@ -218,7 +218,7 @@ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
                                               uint32_t key)
 {
        struct ttm_object_device *tdev = tfile->tdev;
-       struct ttm_base_object *base;
+       struct ttm_base_object *uninitialized_var(base);
        struct drm_hash_item *hash;
        int ret;
 
index 5e93a52d4f2c7a6183a36e70c976d8a1bbf9871e..210d50365162d39d8b2048ba3d8c0e567ed95bf9 100644 (file)
@@ -170,7 +170,7 @@ void ttm_tt_destroy(struct ttm_tt *ttm)
                ttm_tt_unbind(ttm);
        }
 
-       if (likely(ttm->pages != NULL)) {
+       if (ttm->state == tt_unbound) {
                ttm->bdev->driver->ttm_tt_unpopulate(ttm);
        }
 
index 8dbe9d0ae9a73840ae6270bac3776ca239954a11..8bf646183bac837a24f335bb46237c5c4a5d5e43 100644 (file)
@@ -97,7 +97,6 @@ int udl_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address, page);
        switch (ret) {
        case -EAGAIN:
-               set_need_resched();
        case 0:
        case -ERESTARTSYS:
                return VM_FAULT_NOPAGE;
index ae88a97f976e614fe776d451bd5e5abc5ec1e01e..b8470b1a10fe8b40bef83386a0476591e5a067d7 100644 (file)
@@ -94,7 +94,6 @@ EXPORT_SYMBOL_GPL(hid_register_report);
 static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
 {
        struct hid_field *field;
-       int i;
 
        if (report->maxfield == HID_MAX_FIELDS) {
                hid_err(report->device, "too many fields in report\n");
@@ -113,9 +112,6 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
        field->value = (s32 *)(field->usage + usages);
        field->report = report;
 
-       for (i = 0; i < usages; i++)
-               field->usage[i].usage_index = i;
-
        return field;
 }
 
@@ -226,9 +222,9 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
 {
        struct hid_report *report;
        struct hid_field *field;
-       int usages;
+       unsigned usages;
        unsigned offset;
-       int i;
+       unsigned i;
 
        report = hid_register_report(parser->device, report_type, parser->global.report_id);
        if (!report) {
@@ -255,7 +251,8 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
        if (!parser->local.usage_index) /* Ignore padding fields */
                return 0;
 
-       usages = max_t(int, parser->local.usage_index, parser->global.report_count);
+       usages = max_t(unsigned, parser->local.usage_index,
+                                parser->global.report_count);
 
        field = hid_register_field(report, usages, parser->global.report_count);
        if (!field)
@@ -266,13 +263,14 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
        field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
 
        for (i = 0; i < usages; i++) {
-               int j = i;
+               unsigned j = i;
                /* Duplicate the last usage we parsed if we have excess values */
                if (i >= parser->local.usage_index)
                        j = parser->local.usage_index - 1;
                field->usage[i].hid = parser->local.usage[j];
                field->usage[i].collection_index =
                        parser->local.collection_index[j];
+               field->usage[i].usage_index = i;
        }
 
        field->maxusage = usages;
@@ -801,6 +799,64 @@ int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size)
 }
 EXPORT_SYMBOL_GPL(hid_parse_report);
 
+static const char * const hid_report_names[] = {
+       "HID_INPUT_REPORT",
+       "HID_OUTPUT_REPORT",
+       "HID_FEATURE_REPORT",
+};
+/**
+ * hid_validate_values - validate existing device report's value indexes
+ *
+ * @device: hid device
+ * @type: which report type to examine
+ * @id: which report ID to examine (0 for first)
+ * @field_index: which report field to examine
+ * @report_counts: expected number of values
+ *
+ * Validate the number of values in a given field of a given report, after
+ * parsing.
+ */
+struct hid_report *hid_validate_values(struct hid_device *hid,
+                                      unsigned int type, unsigned int id,
+                                      unsigned int field_index,
+                                      unsigned int report_counts)
+{
+       struct hid_report *report;
+
+       if (type > HID_FEATURE_REPORT) {
+               hid_err(hid, "invalid HID report type %u\n", type);
+               return NULL;
+       }
+
+       if (id >= HID_MAX_IDS) {
+               hid_err(hid, "invalid HID report id %u\n", id);
+               return NULL;
+       }
+
+       /*
+        * Explicitly not using hid_get_report() here since it depends on
+        * ->numbered being checked, which may not always be the case when
+        * drivers go to access report values.
+        */
+       report = hid->report_enum[type].report_id_hash[id];
+       if (!report) {
+               hid_err(hid, "missing %s %u\n", hid_report_names[type], id);
+               return NULL;
+       }
+       if (report->maxfield <= field_index) {
+               hid_err(hid, "not enough fields in %s %u\n",
+                       hid_report_names[type], id);
+               return NULL;
+       }
+       if (report->field[field_index]->report_count < report_counts) {
+               hid_err(hid, "not enough values in %s %u field %u\n",
+                       hid_report_names[type], id, field_index);
+               return NULL;
+       }
+       return report;
+}
+EXPORT_SYMBOL_GPL(hid_validate_values);
+
 /**
  * hid_open_report - open a driver-specific device report
  *
@@ -1296,7 +1352,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
                        goto out;
        }
 
-       if (hid->claimed != HID_CLAIMED_HIDRAW) {
+       if (hid->claimed != HID_CLAIMED_HIDRAW && report->maxfield) {
                for (a = 0; a < report->maxfield; a++)
                        hid_input_field(hid, report->field[a], cdata, interrupt);
                hdrv = hid->driver;
index b420f4a0fd28101e0e697a48e581fe31826f9a56..8741d953dcc80acb552bac187ffe6997ad95ca4e 100644 (file)
@@ -485,6 +485,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
        if (field->flags & HID_MAIN_ITEM_CONSTANT)
                goto ignore;
 
+       /* Ignore if report count is out of bounds. */
+       if (field->report_count < 1)
+               goto ignore;
+
        /* only LED usages are supported in output fields */
        if (field->report_type == HID_OUTPUT_REPORT &&
                        (usage->hid & HID_USAGE_PAGE) != HID_UP_LED) {
@@ -1236,7 +1240,11 @@ static void report_features(struct hid_device *hid)
 
        rep_enum = &hid->report_enum[HID_FEATURE_REPORT];
        list_for_each_entry(rep, &rep_enum->report_list, list)
-               for (i = 0; i < rep->maxfield; i++)
+               for (i = 0; i < rep->maxfield; i++) {
+                       /* Ignore if report count is out of bounds. */
+                       if (rep->field[i]->report_count < 1)
+                               continue;
+
                        for (j = 0; j < rep->field[i]->maxusage; j++) {
                                /* Verify if Battery Strength feature is available */
                                hidinput_setup_battery(hid, HID_FEATURE_REPORT, rep->field[i]);
@@ -1245,6 +1253,7 @@ static void report_features(struct hid_device *hid)
                                        drv->feature_mapping(hid, rep->field[i],
                                                             rep->field[i]->usage + j);
                        }
+               }
 }
 
 static struct hid_input *hidinput_allocate(struct hid_device *hid)
index 07837f5a4eb88adaae7ba8c20f4517a15754b440..31cf29a6ba17551ff5244a0f243d48a4719e662c 100644 (file)
@@ -339,7 +339,15 @@ static int tpkbd_probe_tp(struct hid_device *hdev)
        struct tpkbd_data_pointer *data_pointer;
        size_t name_sz = strlen(dev_name(dev)) + 16;
        char *name_mute, *name_micmute;
-       int ret;
+       int i, ret;
+
+       /* Validate required reports. */
+       for (i = 0; i < 4; i++) {
+               if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1))
+                       return -ENODEV;
+       }
+       if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2))
+               return -ENODEV;
 
        if (sysfs_create_group(&hdev->dev.kobj,
                                &tpkbd_attr_group_pointer)) {
@@ -406,22 +414,27 @@ static int tpkbd_probe(struct hid_device *hdev,
        ret = hid_parse(hdev);
        if (ret) {
                hid_err(hdev, "hid_parse failed\n");
-               goto err_free;
+               goto err;
        }
 
        ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
        if (ret) {
                hid_err(hdev, "hid_hw_start failed\n");
-               goto err_free;
+               goto err;
        }
 
        uhdev = (struct usbhid_device *) hdev->driver_data;
 
-       if (uhdev->ifnum == 1)
-               return tpkbd_probe_tp(hdev);
+       if (uhdev->ifnum == 1) {
+               ret = tpkbd_probe_tp(hdev);
+               if (ret)
+                       goto err_hid;
+       }
 
        return 0;
-err_free:
+err_hid:
+       hid_hw_stop(hdev);
+err:
        return ret;
 }
 
index b3cd1507dda2eab0eb09c0c48e006505eabac153..1a42eaa6ca0234a054631544732db69484c5eb82 100644 (file)
@@ -64,26 +64,13 @@ int lg2ff_init(struct hid_device *hid)
        struct hid_report *report;
        struct hid_input *hidinput = list_entry(hid->inputs.next,
                                                struct hid_input, list);
-       struct list_head *report_list =
-                       &hid->report_enum[HID_OUTPUT_REPORT].report_list;
        struct input_dev *dev = hidinput->input;
        int error;
 
-       if (list_empty(report_list)) {
-               hid_err(hid, "no output report found\n");
+       /* Check that the report looks ok */
+       report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7);
+       if (!report)
                return -ENODEV;
-       }
-
-       report = list_entry(report_list->next, struct hid_report, list);
-
-       if (report->maxfield < 1) {
-               hid_err(hid, "output report is empty\n");
-               return -ENODEV;
-       }
-       if (report->field[0]->report_count < 7) {
-               hid_err(hid, "not enough values in the field\n");
-               return -ENODEV;
-       }
 
        lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL);
        if (!lg2ff)
index e52f181f6aa14dd4fd8229ce2ecb379ccf80533c..8c2da183d3bc71354d82b635b5234a70ca106850 100644 (file)
@@ -66,10 +66,11 @@ static int hid_lg3ff_play(struct input_dev *dev, void *data,
        int x, y;
 
 /*
- * Maxusage should always be 63 (maximum fields)
- * likely a better way to ensure this data is clean
+ * Available values in the field should always be 63, but we only use up to
+ * 35. Instead, clear the entire area, however big it is.
  */
-       memset(report->field[0]->value, 0, sizeof(__s32)*report->field[0]->maxusage);
+       memset(report->field[0]->value, 0,
+              sizeof(__s32) * report->field[0]->report_count);
 
        switch (effect->type) {
        case FF_CONSTANT:
@@ -129,32 +130,14 @@ static const signed short ff3_joystick_ac[] = {
 int lg3ff_init(struct hid_device *hid)
 {
        struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
-       struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
        struct input_dev *dev = hidinput->input;
-       struct hid_report *report;
-       struct hid_field *field;
        const signed short *ff_bits = ff3_joystick_ac;
        int error;
        int i;
 
-       /* Find the report to use */
-       if (list_empty(report_list)) {
-               hid_err(hid, "No output report found\n");
-               return -1;
-       }
-
        /* Check that the report looks ok */
-       report = list_entry(report_list->next, struct hid_report, list);
-       if (!report) {
-               hid_err(hid, "NULL output report\n");
-               return -1;
-       }
-
-       field = report->field[0];
-       if (!field) {
-               hid_err(hid, "NULL field\n");
-               return -1;
-       }
+       if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 35))
+               return -ENODEV;
 
        /* Assume single fixed device G940 */
        for (i = 0; ff_bits[i] >= 0; i++)
index 0ddae2a00d59a595b4d7ad436dc8cedcfdde7b71..8782fe1aaa0796e42d17f1ad39d1c72c652d58c5 100644 (file)
@@ -484,34 +484,16 @@ static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cde
 int lg4ff_init(struct hid_device *hid)
 {
        struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
-       struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
        struct input_dev *dev = hidinput->input;
-       struct hid_report *report;
-       struct hid_field *field;
        struct lg4ff_device_entry *entry;
        struct lg_drv_data *drv_data;
        struct usb_device_descriptor *udesc;
        int error, i, j;
        __u16 bcdDevice, rev_maj, rev_min;
 
-       /* Find the report to use */
-       if (list_empty(report_list)) {
-               hid_err(hid, "No output report found\n");
-               return -1;
-       }
-
        /* Check that the report looks ok */
-       report = list_entry(report_list->next, struct hid_report, list);
-       if (!report) {
-               hid_err(hid, "NULL output report\n");
+       if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7))
                return -1;
-       }
-
-       field = report->field[0];
-       if (!field) {
-               hid_err(hid, "NULL field\n");
-               return -1;
-       }
 
        /* Check what wheel has been connected */
        for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) {
index d7ea8c845b4038ec2a943baa6f169ade22e82e3d..e1394af0ae7ba06701ad106896fb9391c417d6c0 100644 (file)
@@ -128,27 +128,14 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude)
 int lgff_init(struct hid_device* hid)
 {
        struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
-       struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
        struct input_dev *dev = hidinput->input;
-       struct hid_report *report;
-       struct hid_field *field;
        const signed short *ff_bits = ff_joystick;
        int error;
        int i;
 
-       /* Find the report to use */
-       if (list_empty(report_list)) {
-               hid_err(hid, "No output report found\n");
-               return -1;
-       }
-
        /* Check that the report looks ok */
-       report = list_entry(report_list->next, struct hid_report, list);
-       field = report->field[0];
-       if (!field) {
-               hid_err(hid, "NULL field\n");
-               return -1;
-       }
+       if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7))
+               return -ENODEV;
 
        for (i = 0; i < ARRAY_SIZE(devices); i++) {
                if (dev->id.vendor == devices[i].idVendor &&
index 7800b141056243400bfa316b7289e2c8431aa82a..2e5302462efb088b3f3019b26fedfc816ca493f5 100644 (file)
@@ -461,7 +461,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
        struct hid_report *report;
        struct hid_report_enum *output_report_enum;
        u8 *data = (u8 *)(&dj_report->device_index);
-       int i;
+       unsigned int i;
 
        output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT];
        report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
@@ -471,7 +471,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
                return -ENODEV;
        }
 
-       for (i = 0; i < report->field[0]->report_count; i++)
+       for (i = 0; i < DJREPORT_SHORT_LENGTH - 1; i++)
                report->field[0]->value[i] = data[i];
 
        hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
@@ -791,6 +791,12 @@ static int logi_dj_probe(struct hid_device *hdev,
                goto hid_parse_fail;
        }
 
+       if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, REPORT_ID_DJ_SHORT,
+                                0, DJREPORT_SHORT_LENGTH - 1)) {
+               retval = -ENODEV;
+               goto hid_parse_fail;
+       }
+
        /* Starts the usb device and connects to upper interfaces hiddev and
         * hidraw */
        retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
index ac28f08c38660b0051500242f8562b587007cf90..5e5fe1b8eebb73e5d4533997a889eee87d637150 100644 (file)
@@ -101,9 +101,9 @@ struct mt_device {
        unsigned last_slot_field;       /* the last field of a slot */
        unsigned mt_report_id;  /* the report ID of the multitouch device */
        unsigned pen_report_id; /* the report ID of the pen device */
-       __s8 inputmode;         /* InputMode HID feature, -1 if non-existent */
-       __s8 inputmode_index;   /* InputMode HID feature index in the report */
-       __s8 maxcontact_report_id;      /* Maximum Contact Number HID feature,
+       __s16 inputmode;        /* InputMode HID feature, -1 if non-existent */
+       __s16 inputmode_index;  /* InputMode HID feature index in the report */
+       __s16 maxcontact_report_id;     /* Maximum Contact Number HID feature,
                                   -1 if non-existent */
        __u8 num_received;      /* how many contacts we received */
        __u8 num_expected;      /* expected last contact index */
@@ -312,20 +312,18 @@ static void mt_feature_mapping(struct hid_device *hdev,
                struct hid_field *field, struct hid_usage *usage)
 {
        struct mt_device *td = hid_get_drvdata(hdev);
-       int i;
 
        switch (usage->hid) {
        case HID_DG_INPUTMODE:
-               td->inputmode = field->report->id;
-               td->inputmode_index = 0; /* has to be updated below */
-
-               for (i=0; i < field->maxusage; i++) {
-                       if (field->usage[i].hid == usage->hid) {
-                               td->inputmode_index = i;
-                               break;
-                       }
+               /* Ignore if value index is out of bounds. */
+               if (usage->usage_index >= field->report_count) {
+                       dev_err(&hdev->dev, "HID_DG_INPUTMODE out of range\n");
+                       break;
                }
 
+               td->inputmode = field->report->id;
+               td->inputmode_index = usage->usage_index;
+
                break;
        case HID_DG_CONTACTMAX:
                td->maxcontact_report_id = field->report->id;
@@ -511,6 +509,10 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                        mt_store_field(usage, td, hi);
                        return 1;
                case HID_DG_CONTACTCOUNT:
+                       /* Ignore if indexes are out of bounds. */
+                       if (field->index >= field->report->maxfield ||
+                           usage->usage_index >= field->report_count)
+                               return 1;
                        td->cc_index = field->index;
                        td->cc_value_index = usage->usage_index;
                        return 1;
index 30dbb6b40bbf17e93c63b2bd6d3eb3b7f8111593..b18320db5f7d18cba708ecd306ee3f394abebddb 100644 (file)
@@ -537,6 +537,10 @@ static int buzz_init(struct hid_device *hdev)
        drv_data = hid_get_drvdata(hdev);
        BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER));
 
+       /* Validate expected report characteristics. */
+       if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7))
+               return -ENODEV;
+
        buzz = kzalloc(sizeof(*buzz), GFP_KERNEL);
        if (!buzz) {
                hid_err(hdev, "Insufficient memory, cannot allocate driver data\n");
index d1649119211277275840a1bee984ed93de28c025..29f328f411fb5454e03d46406c880fc9a5de0516 100644 (file)
@@ -249,6 +249,11 @@ static int steelseries_srws1_probe(struct hid_device *hdev,
                goto err_free;
        }
 
+       if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 16)) {
+               ret = -ENODEV;
+               goto err_free;
+       }
+
        ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
        if (ret) {
                hid_err(hdev, "hw start failed\n");
index 6ec28a37c146ab58d623ef1ccaafc38b3dcd9477..a29756c6ca02d064faee371143e750b19094f26c 100644 (file)
@@ -68,21 +68,13 @@ static int zpff_init(struct hid_device *hid)
        struct hid_report *report;
        struct hid_input *hidinput = list_entry(hid->inputs.next,
                                                struct hid_input, list);
-       struct list_head *report_list =
-                       &hid->report_enum[HID_OUTPUT_REPORT].report_list;
        struct input_dev *dev = hidinput->input;
-       int error;
+       int i, error;
 
-       if (list_empty(report_list)) {
-               hid_err(hid, "no output report found\n");
-               return -ENODEV;
-       }
-
-       report = list_entry(report_list->next, struct hid_report, list);
-
-       if (report->maxfield < 4) {
-               hid_err(hid, "not enough fields in report\n");
-               return -ENODEV;
+       for (i = 0; i < 4; i++) {
+               report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, i, 1);
+               if (!report)
+                       return -ENODEV;
        }
 
        zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL);
index 8f4743ab5fb279ae416fbce5ff4e16e58db45eaf..936093e0271e3c7fffccce7fe0e688c4d6f3ad01 100644 (file)
@@ -195,7 +195,7 @@ int vmbus_connect(void)
 
        do {
                ret = vmbus_negotiate_version(msginfo, version);
-               if (ret)
+               if (ret == -ETIMEDOUT)
                        goto cleanup;
 
                if (vmbus_connection.conn_state == CONNECTED)
index 28b03325b8729ffdf2d3356538dc2515b5af5de2..09988b2896226552e4be5cd69d5f09ba3f842d11 100644 (file)
 /*
  * Pre win8 version numbers used in ws2008 and ws 2008 r2 (win7)
  */
+#define WS2008_SRV_MAJOR       1
+#define WS2008_SRV_MINOR       0
+#define WS2008_SRV_VERSION     (WS2008_SRV_MAJOR << 16 | WS2008_SRV_MINOR)
+
 #define WIN7_SRV_MAJOR   3
 #define WIN7_SRV_MINOR   0
-#define WIN7_SRV_MAJOR_MINOR     (WIN7_SRV_MAJOR << 16 | WIN7_SRV_MINOR)
+#define WIN7_SRV_VERSION     (WIN7_SRV_MAJOR << 16 | WIN7_SRV_MINOR)
 
 #define WIN8_SRV_MAJOR   4
 #define WIN8_SRV_MINOR   0
-#define WIN8_SRV_MAJOR_MINOR     (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR)
+#define WIN8_SRV_VERSION     (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR)
 
 /*
  * Global state maintained for transaction that is being processed.
@@ -587,6 +591,8 @@ void hv_kvp_onchannelcallback(void *context)
 
        struct icmsg_hdr *icmsghdrp;
        struct icmsg_negotiate *negop = NULL;
+       int util_fw_version;
+       int kvp_srv_version;
 
        if (kvp_transaction.active) {
                /*
@@ -606,17 +612,26 @@ void hv_kvp_onchannelcallback(void *context)
 
                if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
                        /*
-                        * We start with win8 version and if the host cannot
-                        * support that we use the previous version.
+                        * Based on the host, select appropriate
+                        * framework and service versions we will
+                        * negotiate.
                         */
-                       if (vmbus_prep_negotiate_resp(icmsghdrp, negop,
-                                recv_buffer, UTIL_FW_MAJOR_MINOR,
-                                WIN8_SRV_MAJOR_MINOR))
-                               goto done;
-
+                       switch (vmbus_proto_version) {
+                       case (VERSION_WS2008):
+                               util_fw_version = UTIL_WS2K8_FW_VERSION;
+                               kvp_srv_version = WS2008_SRV_VERSION;
+                               break;
+                       case (VERSION_WIN7):
+                               util_fw_version = UTIL_FW_VERSION;
+                               kvp_srv_version = WIN7_SRV_VERSION;
+                               break;
+                       default:
+                               util_fw_version = UTIL_FW_VERSION;
+                               kvp_srv_version = WIN8_SRV_VERSION;
+                       }
                        vmbus_prep_negotiate_resp(icmsghdrp, negop,
-                                recv_buffer, UTIL_FW_MAJOR_MINOR,
-                                WIN7_SRV_MAJOR_MINOR);
+                                recv_buffer, util_fw_version,
+                                kvp_srv_version);
 
                } else {
                        kvp_msg = (struct hv_kvp_msg *)&recv_buffer[
@@ -649,7 +664,6 @@ void hv_kvp_onchannelcallback(void *context)
                        return;
 
                }
-done:
 
                icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
                        | ICMSGHDRFLAG_RESPONSE;
index e4572f3f2834fe917c5f4dbf097a30cbc8f3b383..0c354622437681d1b6dd157f718bb27cf8dbdbed 100644 (file)
@@ -26,7 +26,7 @@
 
 #define VSS_MAJOR  5
 #define VSS_MINOR  0
-#define VSS_MAJOR_MINOR    (VSS_MAJOR << 16 | VSS_MINOR)
+#define VSS_VERSION    (VSS_MAJOR << 16 | VSS_MINOR)
 
 
 
@@ -190,8 +190,8 @@ void hv_vss_onchannelcallback(void *context)
 
                if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
                        vmbus_prep_negotiate_resp(icmsghdrp, negop,
-                                recv_buffer, UTIL_FW_MAJOR_MINOR,
-                                VSS_MAJOR_MINOR);
+                                recv_buffer, UTIL_FW_VERSION,
+                                VSS_VERSION);
                } else {
                        vss_msg = (struct hv_vss_msg *)&recv_buffer[
                                sizeof(struct vmbuspipe_hdr) +
index cb82233541b196a53177007ebb4520a9e4112442..273e3ddb3a20b00c5d1ae03bab6368c5fcfbc26f 100644 (file)
 #include <linux/reboot.h>
 #include <linux/hyperv.h>
 
-#define SHUTDOWN_MAJOR 3
-#define SHUTDOWN_MINOR  0
-#define SHUTDOWN_MAJOR_MINOR   (SHUTDOWN_MAJOR << 16 | SHUTDOWN_MINOR)
 
-#define TIMESYNCH_MAJOR        3
-#define TIMESYNCH_MINOR 0
-#define TIMESYNCH_MAJOR_MINOR  (TIMESYNCH_MAJOR << 16 | TIMESYNCH_MINOR)
+#define SD_MAJOR       3
+#define SD_MINOR       0
+#define SD_VERSION     (SD_MAJOR << 16 | SD_MINOR)
 
-#define HEARTBEAT_MAJOR        3
-#define HEARTBEAT_MINOR 0
-#define HEARTBEAT_MAJOR_MINOR  (HEARTBEAT_MAJOR << 16 | HEARTBEAT_MINOR)
+#define SD_WS2008_MAJOR                1
+#define SD_WS2008_VERSION      (SD_WS2008_MAJOR << 16 | SD_MINOR)
+
+#define TS_MAJOR       3
+#define TS_MINOR       0
+#define TS_VERSION     (TS_MAJOR << 16 | TS_MINOR)
+
+#define TS_WS2008_MAJOR                1
+#define TS_WS2008_VERSION      (TS_WS2008_MAJOR << 16 | TS_MINOR)
+
+#define HB_MAJOR       3
+#define HB_MINOR 0
+#define HB_VERSION     (HB_MAJOR << 16 | HB_MINOR)
+
+#define HB_WS2008_MAJOR        1
+#define HB_WS2008_VERSION      (HB_WS2008_MAJOR << 16 | HB_MINOR)
+
+static int sd_srv_version;
+static int ts_srv_version;
+static int hb_srv_version;
+static int util_fw_version;
 
 static void shutdown_onchannelcallback(void *context);
 static struct hv_util_service util_shutdown = {
@@ -99,8 +114,8 @@ static void shutdown_onchannelcallback(void *context)
 
                if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
                        vmbus_prep_negotiate_resp(icmsghdrp, negop,
-                                       shut_txf_buf, UTIL_FW_MAJOR_MINOR,
-                                       SHUTDOWN_MAJOR_MINOR);
+                                       shut_txf_buf, util_fw_version,
+                                       sd_srv_version);
                } else {
                        shutdown_msg =
                                (struct shutdown_msg_data *)&shut_txf_buf[
@@ -216,6 +231,7 @@ static void timesync_onchannelcallback(void *context)
        struct icmsg_hdr *icmsghdrp;
        struct ictimesync_data *timedatap;
        u8 *time_txf_buf = util_timesynch.recv_buffer;
+       struct icmsg_negotiate *negop = NULL;
 
        vmbus_recvpacket(channel, time_txf_buf,
                         PAGE_SIZE, &recvlen, &requestid);
@@ -225,9 +241,10 @@ static void timesync_onchannelcallback(void *context)
                                sizeof(struct vmbuspipe_hdr)];
 
                if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
-                       vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf,
-                                               UTIL_FW_MAJOR_MINOR,
-                                               TIMESYNCH_MAJOR_MINOR);
+                       vmbus_prep_negotiate_resp(icmsghdrp, negop,
+                                               time_txf_buf,
+                                               util_fw_version,
+                                               ts_srv_version);
                } else {
                        timedatap = (struct ictimesync_data *)&time_txf_buf[
                                sizeof(struct vmbuspipe_hdr) +
@@ -257,6 +274,7 @@ static void heartbeat_onchannelcallback(void *context)
        struct icmsg_hdr *icmsghdrp;
        struct heartbeat_msg_data *heartbeat_msg;
        u8 *hbeat_txf_buf = util_heartbeat.recv_buffer;
+       struct icmsg_negotiate *negop = NULL;
 
        vmbus_recvpacket(channel, hbeat_txf_buf,
                         PAGE_SIZE, &recvlen, &requestid);
@@ -266,9 +284,9 @@ static void heartbeat_onchannelcallback(void *context)
                                sizeof(struct vmbuspipe_hdr)];
 
                if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
-                       vmbus_prep_negotiate_resp(icmsghdrp, NULL,
-                               hbeat_txf_buf, UTIL_FW_MAJOR_MINOR,
-                               HEARTBEAT_MAJOR_MINOR);
+                       vmbus_prep_negotiate_resp(icmsghdrp, negop,
+                               hbeat_txf_buf, util_fw_version,
+                               hb_srv_version);
                } else {
                        heartbeat_msg =
                                (struct heartbeat_msg_data *)&hbeat_txf_buf[
@@ -321,6 +339,25 @@ static int util_probe(struct hv_device *dev,
                goto error;
 
        hv_set_drvdata(dev, srv);
+       /*
+        * Based on the host; initialize the framework and
+        * service version numbers we will negotiate.
+        */
+       switch (vmbus_proto_version) {
+       case (VERSION_WS2008):
+               util_fw_version = UTIL_WS2K8_FW_VERSION;
+               sd_srv_version = SD_WS2008_VERSION;
+               ts_srv_version = TS_WS2008_VERSION;
+               hb_srv_version = HB_WS2008_VERSION;
+               break;
+
+       default:
+               util_fw_version = UTIL_FW_VERSION;
+               sd_srv_version = SD_VERSION;
+               ts_srv_version = TS_VERSION;
+               hb_srv_version = HB_VERSION;
+       }
+
        return 0;
 
 error:
index 62c2e32e25ef6823290380074d50829af30e5751..98814d12a6040e00a9a56d80686d9392c78b3765 100644 (file)
@@ -525,16 +525,25 @@ static int applesmc_init_smcreg_try(void)
 {
        struct applesmc_registers *s = &smcreg;
        bool left_light_sensor, right_light_sensor;
+       unsigned int count;
        u8 tmp[1];
        int ret;
 
        if (s->init_complete)
                return 0;
 
-       ret = read_register_count(&s->key_count);
+       ret = read_register_count(&count);
        if (ret)
                return ret;
 
+       if (s->cache && s->key_count != count) {
+               pr_warn("key count changed from %d to %d\n",
+                       s->key_count, count);
+               kfree(s->cache);
+               s->cache = NULL;
+       }
+       s->key_count = count;
+
        if (!s->cache)
                s->cache = kcalloc(s->key_count, sizeof(*s->cache), GFP_KERNEL);
        if (!s->cache)
index dbecf08399f86dd30baa7fa7b8964e2daf616bcb..5888feef1ac5a959b5f0471a3fb71b9a2b00bada 100644 (file)
@@ -98,6 +98,8 @@
 
 #define DW_IC_ERR_TX_ABRT      0x1
 
+#define DW_IC_TAR_10BITADDR_MASTER BIT(12)
+
 /*
  * status codes
  */
@@ -388,22 +390,34 @@ static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
 static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
 {
        struct i2c_msg *msgs = dev->msgs;
-       u32 ic_con;
+       u32 ic_con, ic_tar = 0;
 
        /* Disable the adapter */
        __i2c_dw_enable(dev, false);
 
-       /* set the slave (target) address */
-       dw_writel(dev, msgs[dev->msg_write_idx].addr, DW_IC_TAR);
-
        /* if the slave address is ten bit address, enable 10BITADDR */
        ic_con = dw_readl(dev, DW_IC_CON);
-       if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
+       if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) {
                ic_con |= DW_IC_CON_10BITADDR_MASTER;
-       else
+               /*
+                * If I2C_DYNAMIC_TAR_UPDATE is set, the 10-bit addressing
+                * mode has to be enabled via bit 12 of IC_TAR register.
+                * We set it always as I2C_DYNAMIC_TAR_UPDATE can't be
+                * detected from registers.
+                */
+               ic_tar = DW_IC_TAR_10BITADDR_MASTER;
+       } else {
                ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
+       }
+
        dw_writel(dev, ic_con, DW_IC_CON);
 
+       /*
+        * Set the slave (target) address and enable 10-bit addressing mode
+        * if applicable.
+        */
+       dw_writel(dev, msgs[dev->msg_write_idx].addr | ic_tar, DW_IC_TAR);
+
        /* Enable the adapter */
        __i2c_dw_enable(dev, true);
 
index 8ed79a086f858012b0f22b291834a5fb357d075c..1672effbcebb23894b99deac27bb84d595fa28d2 100644 (file)
@@ -393,6 +393,9 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
 
        desc = &priv->hw[priv->head];
 
+       /* Initialize the DMA buffer */
+       memset(priv->dma_buffer, 0, sizeof(priv->dma_buffer));
+
        /* Initialize the descriptor */
        memset(desc, 0, sizeof(struct ismt_desc));
        desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, read_write);
index 7f3a4744349476f941a4500c9edc6a65a6da0fe2..d3e9cc3153a973dc62f99d7d607e003179f41f9d 100644 (file)
@@ -234,9 +234,9 @@ static int mv64xxx_i2c_offload_msg(struct mv64xxx_i2c_data *drv_data)
                ctrl_reg |= MV64XXX_I2C_BRIDGE_CONTROL_WR |
                    (msg->len - 1) << MV64XXX_I2C_BRIDGE_CONTROL_TX_SIZE_SHIFT;
 
-               writel_relaxed(data_reg_lo,
+               writel(data_reg_lo,
                        drv_data->reg_base + MV64XXX_I2C_REG_TX_DATA_LO);
-               writel_relaxed(data_reg_hi,
+               writel(data_reg_hi,
                        drv_data->reg_base + MV64XXX_I2C_REG_TX_DATA_HI);
 
        } else {
@@ -697,6 +697,7 @@ static const struct of_device_id mv64xxx_i2c_of_match_table[] = {
 MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table);
 
 #ifdef CONFIG_OF
+#ifdef CONFIG_HAVE_CLK
 static int
 mv64xxx_calc_freq(const int tclk, const int n, const int m)
 {
@@ -726,16 +727,12 @@ mv64xxx_find_baud_factors(const u32 req_freq, const u32 tclk, u32 *best_n,
                return false;
        return true;
 }
+#endif /* CONFIG_HAVE_CLK */
 
 static int
 mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
                  struct device *dev)
 {
-       const struct of_device_id *device;
-       struct device_node *np = dev->of_node;
-       u32 bus_freq, tclk;
-       int rc = 0;
-
        /* CLK is mandatory when using DT to describe the i2c bus. We
         * need to know tclk in order to calculate bus clock
         * factors.
@@ -744,6 +741,11 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
        /* Have OF but no CLK */
        return -ENODEV;
 #else
+       const struct of_device_id *device;
+       struct device_node *np = dev->of_node;
+       u32 bus_freq, tclk;
+       int rc = 0;
+
        if (IS_ERR(drv_data->clk)) {
                rc = -ENODEV;
                goto out;
index 3535f3c0f7b43233b09123c89b4727fc302cba3b..3747b9bf67d6440f684bcff945a2a85b93f6fe6c 100644 (file)
@@ -1178,8 +1178,6 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
 
        i2c_del_adapter(&i2c->adap);
 
-       clk_disable_unprepare(i2c->clk);
-
        if (pdev->dev.of_node && IS_ERR(i2c->pctrl))
                s3c24xx_i2c_dt_gpio_free(i2c);
 
index 12e32e6b41037c334c1eb8b3cef0e70145f8d228..81e3dc260993124981d45cacb9e472e9221d7b8a 100644 (file)
@@ -620,7 +620,7 @@ static int bma180_remove(struct i2c_client *client)
 #ifdef CONFIG_PM_SLEEP
 static int bma180_suspend(struct device *dev)
 {
-       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
        struct bma180_data *data = iio_priv(indio_dev);
        int ret;
 
@@ -633,7 +633,7 @@ static int bma180_suspend(struct device *dev)
 
 static int bma180_resume(struct device *dev)
 {
-       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
        struct bma180_data *data = iio_priv(indio_dev);
        int ret;
 
index 84be63bdf0382b6b44dfa14ff818e72377baf779..0f16b553e063f602e4e83104382827bb55cc72b2 100644 (file)
@@ -556,7 +556,7 @@ static const struct iio_info at91_adc_info = {
 
 static int at91_adc_probe(struct platform_device *pdev)
 {
-       unsigned int prsc, mstrclk, ticks, adc_clk, shtim;
+       unsigned int prsc, mstrclk, ticks, adc_clk, adc_clk_khz, shtim;
        int ret;
        struct iio_dev *idev;
        struct at91_adc_state *st;
@@ -649,6 +649,7 @@ static int at91_adc_probe(struct platform_device *pdev)
         */
        mstrclk = clk_get_rate(st->clk);
        adc_clk = clk_get_rate(st->adc_clk);
+       adc_clk_khz = adc_clk / 1000;
        prsc = (mstrclk / (2 * adc_clk)) - 1;
 
        if (!st->startup_time) {
@@ -662,15 +663,15 @@ static int at91_adc_probe(struct platform_device *pdev)
         * defined in the electrical characteristics of the board, divided by 8.
         * The formula thus is : Startup Time = (ticks + 1) * 8 / ADC Clock
         */
-       ticks = round_up((st->startup_time * adc_clk /
-                         1000000) - 1, 8) / 8;
+       ticks = round_up((st->startup_time * adc_clk_khz /
+                         1000) - 1, 8) / 8;
        /*
         * a minimal Sample and Hold Time is necessary for the ADC to guarantee
         * the best converted final value between two channels selection
         * The formula thus is : Sample and Hold Time = (shtim + 1) / ADCClock
         */
-       shtim = round_up((st->sample_hold_time * adc_clk /
-                         1000000) - 1, 1);
+       shtim = round_up((st->sample_hold_time * adc_clk_khz /
+                         1000) - 1, 1);
 
        reg = AT91_ADC_PRESCAL_(prsc) & st->registers->mr_prescal_mask;
        reg |= AT91_ADC_STARTUP_(ticks) & st->registers->mr_startup_mask;
index d0a79a4bce1c8f5d83410392e3343d779b015e2a..ba6f6a91dfffc63459ca9e92299832e946f740e3 100644 (file)
@@ -185,10 +185,8 @@ static int ad8366_remove(struct spi_device *spi)
 
        iio_device_unregister(indio_dev);
 
-       if (!IS_ERR(reg)) {
+       if (!IS_ERR(reg))
                regulator_disable(reg);
-               regulator_put(reg);
-       }
 
        return 0;
 }
index 9d19ba74f22bd92125501e2827ef51bbae59da13..415f3c6efd7293087cc1d5fa9313e9de308e6245 100644 (file)
@@ -41,6 +41,8 @@ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,
                goto error_ret;
        }
 
+       iio_buffer_init(&cb_buff->buffer);
+
        cb_buff->private = private;
        cb_buff->cb = cb;
        cb_buff->buffer.access = &iio_cb_access;
index 1f4a48e6a82c33f29b8985ad556698f0630e21af..1397b6e0e414c25835aebd829dc2bede15dedee3 100644 (file)
@@ -37,21 +37,21 @@ struct mcp4725_data {
 
 static int mcp4725_suspend(struct device *dev)
 {
-       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-       struct mcp4725_data *data = iio_priv(indio_dev);
+       struct mcp4725_data *data = iio_priv(i2c_get_clientdata(
+               to_i2c_client(dev)));
        u8 outbuf[2];
 
        outbuf[0] = (data->powerdown_mode + 1) << 4;
        outbuf[1] = 0;
        data->powerdown = true;
 
-       return i2c_master_send(to_i2c_client(dev), outbuf, 2);
+       return i2c_master_send(data->client, outbuf, 2);
 }
 
 static int mcp4725_resume(struct device *dev)
 {
-       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-       struct mcp4725_data *data = iio_priv(indio_dev);
+       struct mcp4725_data *data = iio_priv(i2c_get_clientdata(
+               to_i2c_client(dev)));
        u8 outbuf[2];
 
        /* restore previous DAC value */
@@ -59,7 +59,7 @@ static int mcp4725_resume(struct device *dev)
        outbuf[1] = data->dac_value & 0xff;
        data->powerdown = false;
 
-       return i2c_master_send(to_i2c_client(dev), outbuf, 2);
+       return i2c_master_send(data->client, outbuf, 2);
 }
 
 #ifdef CONFIG_PM_SLEEP
index 05c1b74502a37265c86a23edaf97d4e602ead575..9b32253b824be454bf2f6c46bf02acb022b3be46 100644 (file)
@@ -49,11 +49,15 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
 #define iio_buffer_poll_addr (&iio_buffer_poll)
 #define iio_buffer_read_first_n_outer_addr (&iio_buffer_read_first_n_outer)
 
+void iio_disable_all_buffers(struct iio_dev *indio_dev);
+
 #else
 
 #define iio_buffer_poll_addr NULL
 #define iio_buffer_read_first_n_outer_addr NULL
 
+static inline void iio_disable_all_buffers(struct iio_dev *indio_dev) {}
+
 #endif
 
 int iio_device_register_eventset(struct iio_dev *indio_dev);
index e73033f3839a5e1eceba486cadf2825b30fb7027..2710f7245c3b5472b0e924bd22a94f6bc1212b6f 100644 (file)
@@ -460,6 +460,25 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const long *mask,
        return bytes;
 }
 
+void iio_disable_all_buffers(struct iio_dev *indio_dev)
+{
+       struct iio_buffer *buffer, *_buffer;
+
+       if (list_empty(&indio_dev->buffer_list))
+               return;
+
+       if (indio_dev->setup_ops->predisable)
+               indio_dev->setup_ops->predisable(indio_dev);
+
+       list_for_each_entry_safe(buffer, _buffer,
+                       &indio_dev->buffer_list, buffer_list)
+               list_del_init(&buffer->buffer_list);
+
+       indio_dev->currentmode = INDIO_DIRECT_MODE;
+       if (indio_dev->setup_ops->postdisable)
+               indio_dev->setup_ops->postdisable(indio_dev);
+}
+
 int iio_update_buffers(struct iio_dev *indio_dev,
                       struct iio_buffer *insert_buffer,
                       struct iio_buffer *remove_buffer)
@@ -528,8 +547,15 @@ int iio_update_buffers(struct iio_dev *indio_dev,
                         * Note can only occur when adding a buffer.
                         */
                        list_del(&insert_buffer->buffer_list);
-                       indio_dev->active_scan_mask = old_mask;
-                       success = -EINVAL;
+                       if (old_mask) {
+                               indio_dev->active_scan_mask = old_mask;
+                               success = -EINVAL;
+                       }
+                       else {
+                               kfree(compound_mask);
+                               ret = -EINVAL;
+                               goto error_ret;
+                       }
                }
        } else {
                indio_dev->active_scan_mask = compound_mask;
index 97f0297b120f41e7f73d9b5a5cf27887da146a92..f95c6979efd8f58fdf42e2a6d11a645b4191c17d 100644 (file)
@@ -848,13 +848,10 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev)
 static void iio_dev_release(struct device *device)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(device);
-       if (indio_dev->chrdev.dev)
-               cdev_del(&indio_dev->chrdev);
        if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
                iio_device_unregister_trigger_consumer(indio_dev);
        iio_device_unregister_eventset(indio_dev);
        iio_device_unregister_sysfs(indio_dev);
-       iio_device_unregister_debugfs(indio_dev);
 
        ida_simple_remove(&iio_ida, indio_dev->id);
        kfree(indio_dev);
@@ -970,6 +967,8 @@ static int iio_chrdev_open(struct inode *inode, struct file *filp)
        if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags))
                return -EBUSY;
 
+       iio_device_get(indio_dev);
+
        filp->private_data = indio_dev;
 
        return 0;
@@ -983,6 +982,8 @@ static int iio_chrdev_release(struct inode *inode, struct file *filp)
        struct iio_dev *indio_dev = container_of(inode->i_cdev,
                                                struct iio_dev, chrdev);
        clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags);
+       iio_device_put(indio_dev);
+
        return 0;
 }
 
@@ -1052,18 +1053,20 @@ int iio_device_register(struct iio_dev *indio_dev)
                indio_dev->setup_ops == NULL)
                indio_dev->setup_ops = &noop_ring_setup_ops;
 
-       ret = device_add(&indio_dev->dev);
-       if (ret < 0)
-               goto error_unreg_eventset;
        cdev_init(&indio_dev->chrdev, &iio_buffer_fileops);
        indio_dev->chrdev.owner = indio_dev->info->driver_module;
+       indio_dev->chrdev.kobj.parent = &indio_dev->dev.kobj;
        ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1);
        if (ret < 0)
-               goto error_del_device;
-       return 0;
+               goto error_unreg_eventset;
 
-error_del_device:
-       device_del(&indio_dev->dev);
+       ret = device_add(&indio_dev->dev);
+       if (ret < 0)
+               goto error_cdev_del;
+
+       return 0;
+error_cdev_del:
+       cdev_del(&indio_dev->chrdev);
 error_unreg_eventset:
        iio_device_unregister_eventset(indio_dev);
 error_free_sysfs:
@@ -1078,9 +1081,17 @@ EXPORT_SYMBOL(iio_device_register);
 void iio_device_unregister(struct iio_dev *indio_dev)
 {
        mutex_lock(&indio_dev->info_exist_lock);
+
+       device_del(&indio_dev->dev);
+
+       if (indio_dev->chrdev.dev)
+               cdev_del(&indio_dev->chrdev);
+       iio_device_unregister_debugfs(indio_dev);
+
+       iio_disable_all_buffers(indio_dev);
+
        indio_dev->info = NULL;
        mutex_unlock(&indio_dev->info_exist_lock);
-       device_del(&indio_dev->dev);
 }
 EXPORT_SYMBOL(iio_device_unregister);
 subsys_initcall(iio_init);
index 10aa9ef86cece1b80fa09c57d2a52e344e4dfc12..6be65ef5faa9b6e46716857af7ed67d8eb7ea004 100644 (file)
@@ -72,7 +72,8 @@ EXPORT_SYMBOL(iio_push_event);
 static unsigned int iio_event_poll(struct file *filep,
                             struct poll_table_struct *wait)
 {
-       struct iio_event_interface *ev_int = filep->private_data;
+       struct iio_dev *indio_dev = filep->private_data;
+       struct iio_event_interface *ev_int = indio_dev->event_interface;
        unsigned int events = 0;
 
        poll_wait(filep, &ev_int->wait, wait);
@@ -90,7 +91,8 @@ static ssize_t iio_event_chrdev_read(struct file *filep,
                                     size_t count,
                                     loff_t *f_ps)
 {
-       struct iio_event_interface *ev_int = filep->private_data;
+       struct iio_dev *indio_dev = filep->private_data;
+       struct iio_event_interface *ev_int = indio_dev->event_interface;
        unsigned int copied;
        int ret;
 
@@ -121,7 +123,8 @@ error_unlock:
 
 static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
 {
-       struct iio_event_interface *ev_int = filep->private_data;
+       struct iio_dev *indio_dev = filep->private_data;
+       struct iio_event_interface *ev_int = indio_dev->event_interface;
 
        spin_lock_irq(&ev_int->wait.lock);
        __clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
@@ -133,6 +136,8 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
        kfifo_reset_out(&ev_int->det_events);
        spin_unlock_irq(&ev_int->wait.lock);
 
+       iio_device_put(indio_dev);
+
        return 0;
 }
 
@@ -158,12 +163,15 @@ int iio_event_getfd(struct iio_dev *indio_dev)
                return -EBUSY;
        }
        spin_unlock_irq(&ev_int->wait.lock);
-       fd = anon_inode_getfd("iio:event",
-                               &iio_event_chrdev_fileops, ev_int, O_RDONLY);
+       iio_device_get(indio_dev);
+
+       fd = anon_inode_getfd("iio:event", &iio_event_chrdev_fileops,
+                               indio_dev, O_RDONLY);
        if (fd < 0) {
                spin_lock_irq(&ev_int->wait.lock);
                __clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
                spin_unlock_irq(&ev_int->wait.lock);
+               iio_device_put(indio_dev);
        }
        return fd;
 }
@@ -276,7 +284,7 @@ static int iio_device_add_event_sysfs(struct iio_dev *indio_dev,
                        goto error_ret;
                }
                if (chan->modified)
-                       mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel,
+                       mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel2,
                                                  i/IIO_EV_DIR_MAX,
                                                  i%IIO_EV_DIR_MAX);
                else if (chan->differential)
index e8d2849cc81d9110356691caaba587c80afff57e..cab3bc7494a2260214a85874310ac80deca87c0a 100644 (file)
@@ -29,9 +29,9 @@
 #define ST_MAGN_NUMBER_DATA_CHANNELS           3
 
 /* DEFAULT VALUE FOR SENSORS */
-#define ST_MAGN_DEFAULT_OUT_X_L_ADDR           0X04
-#define ST_MAGN_DEFAULT_OUT_Y_L_ADDR           0X08
-#define ST_MAGN_DEFAULT_OUT_Z_L_ADDR           0X06
+#define ST_MAGN_DEFAULT_OUT_X_H_ADDR           0X03
+#define ST_MAGN_DEFAULT_OUT_Y_H_ADDR           0X07
+#define ST_MAGN_DEFAULT_OUT_Z_H_ADDR           0X05
 
 /* FULLSCALE */
 #define ST_MAGN_FS_AVL_1300MG                  1300
 static const struct iio_chan_spec st_magn_16bit_channels[] = {
        ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
                        BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
-                       ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
-                       ST_MAGN_DEFAULT_OUT_X_L_ADDR),
+                       ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_BE, 16, 16,
+                       ST_MAGN_DEFAULT_OUT_X_H_ADDR),
        ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
                        BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
-                       ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
-                       ST_MAGN_DEFAULT_OUT_Y_L_ADDR),
+                       ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_BE, 16, 16,
+                       ST_MAGN_DEFAULT_OUT_Y_H_ADDR),
        ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
                        BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
-                       ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
-                       ST_MAGN_DEFAULT_OUT_Z_L_ADDR),
+                       ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_BE, 16, 16,
+                       ST_MAGN_DEFAULT_OUT_Z_H_ADDR),
        IIO_CHAN_SOFT_TIMESTAMP(3)
 };
 
index 64ccde3f1f7a60ae6693d1e91f117e370bd0141b..6d63883da1ab0e56be798538e1d965b1032eacb7 100644 (file)
@@ -255,12 +255,14 @@ static int tmp006_remove(struct i2c_client *client)
 #ifdef CONFIG_PM_SLEEP
 static int tmp006_suspend(struct device *dev)
 {
-       return tmp006_powerdown(iio_priv(dev_to_iio_dev(dev)));
+       struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+       return tmp006_powerdown(iio_priv(indio_dev));
 }
 
 static int tmp006_resume(struct device *dev)
 {
-       struct tmp006_data *data = iio_priv(dev_to_iio_dev(dev));
+       struct tmp006_data *data = iio_priv(i2c_get_clientdata(
+               to_i2c_client(dev)));
        return i2c_smbus_write_word_swapped(data->client, TMP006_CONFIG,
                data->config | TMP006_CONFIG_MOD_MASK);
 }
index 653ac6bfc57a61147bbeb72fbc598a0d1884b734..6c923c7039a156d10eeaa7a39f339ecd84a360ac 100644 (file)
@@ -1588,7 +1588,7 @@ static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch,
        int resp_data_len;
        int resp_len;
 
-       resp_data_len = (rsp_code == SRP_TSK_MGMT_SUCCESS) ? 0 : 4;
+       resp_data_len = 4;
        resp_len = sizeof(*srp_rsp) + resp_data_len;
 
        srp_rsp = ioctx->ioctx.buf;
@@ -1600,11 +1600,9 @@ static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch,
                                    + atomic_xchg(&ch->req_lim_delta, 0));
        srp_rsp->tag = tag;
 
-       if (rsp_code != SRP_TSK_MGMT_SUCCESS) {
-               srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID;
-               srp_rsp->resp_data_len = cpu_to_be32(resp_data_len);
-               srp_rsp->data[3] = rsp_code;
-       }
+       srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID;
+       srp_rsp->resp_data_len = cpu_to_be32(resp_data_len);
+       srp_rsp->data[3] = rsp_code;
 
        return resp_len;
 }
@@ -2358,6 +2356,8 @@ static void srpt_release_channel_work(struct work_struct *w)
        transport_deregister_session(se_sess);
        ch->sess = NULL;
 
+       ib_destroy_cm_id(ch->cm_id);
+
        srpt_destroy_ch_ib(ch);
 
        srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,
@@ -2368,8 +2368,6 @@ static void srpt_release_channel_work(struct work_struct *w)
        list_del(&ch->list);
        spin_unlock_irq(&sdev->spinlock);
 
-       ib_destroy_cm_id(ch->cm_id);
-
        if (ch->release_done)
                complete(ch->release_done);
 
index f417e89e1e7e47e812fef6e16faf9a19432ce0b4..181c9ba929cdfa131123639862cdefb2587c8cf6 100644 (file)
@@ -377,6 +377,7 @@ struct arm_smmu_cfg {
        u32                             cbar;
        pgd_t                           *pgd;
 };
+#define INVALID_IRPTNDX                        0xff
 
 #define ARM_SMMU_CB_ASID(cfg)          ((cfg)->cbndx)
 #define ARM_SMMU_CB_VMID(cfg)          ((cfg)->cbndx + 1)
@@ -840,7 +841,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
        if (IS_ERR_VALUE(ret)) {
                dev_err(smmu->dev, "failed to request context IRQ %d (%u)\n",
                        root_cfg->irptndx, irq);
-               root_cfg->irptndx = -1;
+               root_cfg->irptndx = INVALID_IRPTNDX;
                goto out_free_context;
        }
 
@@ -869,7 +870,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
        writel_relaxed(0, cb_base + ARM_SMMU_CB_SCTLR);
        arm_smmu_tlb_inv_context(root_cfg);
 
-       if (root_cfg->irptndx != -1) {
+       if (root_cfg->irptndx != INVALID_IRPTNDX) {
                irq = smmu->irqs[smmu->num_global_irqs + root_cfg->irptndx];
                free_irq(irq, domain);
        }
@@ -1857,8 +1858,6 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
                goto out_put_parent;
        }
 
-       arm_smmu_device_reset(smmu);
-
        for (i = 0; i < smmu->num_global_irqs; ++i) {
                err = request_irq(smmu->irqs[i],
                                  arm_smmu_global_fault,
@@ -1876,6 +1875,8 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
        spin_lock(&arm_smmu_devices_lock);
        list_add(&smmu->list, &arm_smmu_devices);
        spin_unlock(&arm_smmu_devices_lock);
+
+       arm_smmu_device_reset(smmu);
        return 0;
 
 out_free_irqs:
@@ -1966,10 +1967,10 @@ static int __init arm_smmu_init(void)
                return ret;
 
        /* Oh, for a proper bus abstraction */
-       if (!iommu_present(&platform_bus_type));
+       if (!iommu_present(&platform_bus_type))
                bus_set_iommu(&platform_bus_type, &arm_smmu_ops);
 
-       if (!iommu_present(&amba_bustype));
+       if (!iommu_present(&amba_bustype))
                bus_set_iommu(&amba_bustype, &arm_smmu_ops);
 
        return 0;
index d0e948084eaf7e2211c323f5976ecc08e5681136..9031171c141b52c5e9175fdbf6eec9bd0c4224b3 100644 (file)
@@ -253,10 +253,9 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
        if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
                return -EINVAL;
 
+       raw_spin_lock(&irq_controller_lock);
        mask = 0xff << shift;
        bit = gic_cpu_map[cpu] << shift;
-
-       raw_spin_lock(&irq_controller_lock);
        val = readl_relaxed(reg) & ~mask;
        writel_relaxed(val | bit, reg);
        raw_spin_unlock(&irq_controller_lock);
@@ -652,7 +651,9 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 {
        int cpu;
-       unsigned long map = 0;
+       unsigned long flags, map = 0;
+
+       raw_spin_lock_irqsave(&irq_controller_lock, flags);
 
        /* Convert our logical CPU mask into a physical one. */
        for_each_cpu(cpu, mask)
@@ -666,7 +667,149 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 
        /* this always happens on GIC0 */
        writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
+
+       raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
+}
+#endif
+
+#ifdef CONFIG_BL_SWITCHER
+/*
+ * gic_send_sgi - send a SGI directly to given CPU interface number
+ *
+ * cpu_id: the ID for the destination CPU interface
+ * irq: the IPI number to send a SGI for
+ */
+void gic_send_sgi(unsigned int cpu_id, unsigned int irq)
+{
+       BUG_ON(cpu_id >= NR_GIC_CPU_IF);
+       cpu_id = 1 << cpu_id;
+       /* this always happens on GIC0 */
+       writel_relaxed((cpu_id << 16) | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
+}
+
+/*
+ * gic_get_cpu_id - get the CPU interface ID for the specified CPU
+ *
+ * @cpu: the logical CPU number to get the GIC ID for.
+ *
+ * Return the CPU interface ID for the given logical CPU number,
+ * or -1 if the CPU number is too large or the interface ID is
+ * unknown (more than one bit set).
+ */
+int gic_get_cpu_id(unsigned int cpu)
+{
+       unsigned int cpu_bit;
+
+       if (cpu >= NR_GIC_CPU_IF)
+               return -1;
+       cpu_bit = gic_cpu_map[cpu];
+       if (cpu_bit & (cpu_bit - 1))
+               return -1;
+       return __ffs(cpu_bit);
 }
+
+/*
+ * gic_migrate_target - migrate IRQs to another CPU interface
+ *
+ * @new_cpu_id: the CPU target ID to migrate IRQs to
+ *
+ * Migrate all peripheral interrupts with a target matching the current CPU
+ * to the interface corresponding to @new_cpu_id.  The CPU interface mapping
+ * is also updated.  Targets to other CPU interfaces are unchanged.
+ * This must be called with IRQs locally disabled.
+ */
+void gic_migrate_target(unsigned int new_cpu_id)
+{
+       unsigned int cur_cpu_id, gic_irqs, gic_nr = 0;
+       void __iomem *dist_base;
+       int i, ror_val, cpu = smp_processor_id();
+       u32 val, cur_target_mask, active_mask;
+
+       if (gic_nr >= MAX_GIC_NR)
+               BUG();
+
+       dist_base = gic_data_dist_base(&gic_data[gic_nr]);
+       if (!dist_base)
+               return;
+       gic_irqs = gic_data[gic_nr].gic_irqs;
+
+       cur_cpu_id = __ffs(gic_cpu_map[cpu]);
+       cur_target_mask = 0x01010101 << cur_cpu_id;
+       ror_val = (cur_cpu_id - new_cpu_id) & 31;
+
+       raw_spin_lock(&irq_controller_lock);
+
+       /* Update the target interface for this logical CPU */
+       gic_cpu_map[cpu] = 1 << new_cpu_id;
+
+       /*
+        * Find all the peripheral interrupts targetting the current
+        * CPU interface and migrate them to the new CPU interface.
+        * We skip DIST_TARGET 0 to 7 as they are read-only.
+        */
+       for (i = 8; i < DIV_ROUND_UP(gic_irqs, 4); i++) {
+               val = readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
+               active_mask = val & cur_target_mask;
+               if (active_mask) {
+                       val &= ~active_mask;
+                       val |= ror32(active_mask, ror_val);
+                       writel_relaxed(val, dist_base + GIC_DIST_TARGET + i*4);
+               }
+       }
+
+       raw_spin_unlock(&irq_controller_lock);
+
+       /*
+        * Now let's migrate and clear any potential SGIs that might be
+        * pending for us (cur_cpu_id).  Since GIC_DIST_SGI_PENDING_SET
+        * is a banked register, we can only forward the SGI using
+        * GIC_DIST_SOFTINT.  The original SGI source is lost but Linux
+        * doesn't use that information anyway.
+        *
+        * For the same reason we do not adjust SGI source information
+        * for previously sent SGIs by us to other CPUs either.
+        */
+       for (i = 0; i < 16; i += 4) {
+               int j;
+               val = readl_relaxed(dist_base + GIC_DIST_SGI_PENDING_SET + i);
+               if (!val)
+                       continue;
+               writel_relaxed(val, dist_base + GIC_DIST_SGI_PENDING_CLEAR + i);
+               for (j = i; j < i + 4; j++) {
+                       if (val & 0xff)
+                               writel_relaxed((1 << (new_cpu_id + 16)) | j,
+                                               dist_base + GIC_DIST_SOFTINT);
+                       val >>= 8;
+               }
+       }
+}
+
+/*
+ * gic_get_sgir_physaddr - get the physical address for the SGI register
+ *
+ * REturn the physical address of the SGI register to be used
+ * by some early assembly code when the kernel is not yet available.
+ */
+static unsigned long gic_dist_physaddr;
+
+unsigned long gic_get_sgir_physaddr(void)
+{
+       if (!gic_dist_physaddr)
+               return 0;
+       return gic_dist_physaddr + GIC_DIST_SOFTINT;
+}
+
+void __init gic_init_physaddr(struct device_node *node)
+{
+       struct resource res;
+       if (of_address_to_resource(node, 0, &res) == 0) {
+               gic_dist_physaddr = res.start;
+               pr_info("GIC physical location is %#lx\n", gic_dist_physaddr);
+       }
+}
+
+#else
+#define gic_init_physaddr(node)  do { } while (0)
 #endif
 
 static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
@@ -850,6 +993,8 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent)
                percpu_offset = 0;
 
        gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset, node);
+       if (!gic_cnt)
+               gic_init_physaddr(node);
 
        if (parent) {
                irq = irq_of_parse_and_map(node, 0);
index 7f910c76ca0a340a967737345c7e733e2c4eced4..3c92780bda09e17843f3cea5c7c35161e103c25c 100644 (file)
@@ -2295,8 +2295,8 @@ _hfcpci_softirq(struct device *dev, void *arg)
 static void
 hfcpci_softirq(void *arg)
 {
-       (void) driver_for_each_device(&hfc_driver.driver, NULL, arg,
-                                     _hfcpci_softirq);
+       WARN_ON_ONCE(driver_for_each_device(&hfc_driver.driver, NULL, arg,
+                                     _hfcpci_softirq) != 0);
 
        /* if next event would be in the past ... */
        if ((s32)(hfc_jiffies + tics - jiffies) <= 0)
index 1063babe1d3ae1ba38ab43ed5cb1ee7407a87fed..36817e0a0b9465df6d1f9f8c4eee7cb0e5d24157 100644 (file)
@@ -314,7 +314,7 @@ Amd7930_empty_Dfifo(struct IsdnCardState *cs, int flag)
 
                                                        t += sprintf(t, "Amd7930: empty_Dfifo cnt: %d |", cs->rcvidx);
                                                        QuickHex(t, cs->rcvbuf, cs->rcvidx);
-                                                       debugl1(cs, cs->dlog);
+                                                       debugl1(cs, "%s", cs->dlog);
                                                }
                                                /* moves received data in sk-buffer */
                                                memcpy(skb_put(skb, cs->rcvidx), cs->rcvbuf, cs->rcvidx);
@@ -406,7 +406,7 @@ Amd7930_fill_Dfifo(struct IsdnCardState *cs)
 
                t += sprintf(t, "Amd7930: fill_Dfifo cnt: %d |", count);
                QuickHex(t, deb_ptr, count);
-               debugl1(cs, cs->dlog);
+               debugl1(cs, "%s", cs->dlog);
        }
        /* AMD interrupts on */
        AmdIrqOn(cs);
index ee9b9a03cffa04d8bfe4a751cb24ce0f2824ec35..d1427bd6452dacd5b2fedfa6d8bf9a33a4207e85 100644 (file)
@@ -285,7 +285,7 @@ hdlc_empty_fifo(struct BCState *bcs, int count)
                t += sprintf(t, "hdlc_empty_fifo %c cnt %d",
                             bcs->channel ? 'B' : 'A', count);
                QuickHex(t, p, count);
-               debugl1(cs, bcs->blog);
+               debugl1(cs, "%s", bcs->blog);
        }
 }
 
@@ -345,7 +345,7 @@ hdlc_fill_fifo(struct BCState *bcs)
                t += sprintf(t, "hdlc_fill_fifo %c cnt %d",
                             bcs->channel ? 'B' : 'A', count);
                QuickHex(t, p, count);
-               debugl1(cs, bcs->blog);
+               debugl1(cs, "%s", bcs->blog);
        }
 }
 
index bf04d2a3cf4afe4614765b2b3d08d32ec77571a6..b33f53b3ca93257a6ec34f409c46e5f1d7662172 100644 (file)
@@ -1896,7 +1896,7 @@ static void EChannel_proc_rcv(struct hisax_d_if *d_if)
                                ptr--;
                                *ptr++ = '\n';
                                *ptr = 0;
-                               HiSax_putstatus(cs, NULL, cs->dlog);
+                               HiSax_putstatus(cs, NULL, "%s", cs->dlog);
                        } else
                                HiSax_putstatus(cs, "LogEcho: ",
                                                "warning Frame too big (%d)",
index 8d0cf6e4dc00590a7d62f455d77bcc192de9dfa1..4fc90de68d18a46941cfd8c629dd5f6624600173 100644 (file)
@@ -427,7 +427,7 @@ Memhscx_empty_fifo(struct BCState *bcs, int count)
                t += sprintf(t, "hscx_empty_fifo %c cnt %d",
                             bcs->hw.hscx.hscx ? 'B' : 'A', count);
                QuickHex(t, ptr, count);
-               debugl1(cs, bcs->blog);
+               debugl1(cs, "%s", bcs->blog);
        }
 }
 
@@ -469,7 +469,7 @@ Memhscx_fill_fifo(struct BCState *bcs)
                t += sprintf(t, "hscx_fill_fifo %c cnt %d",
                             bcs->hw.hscx.hscx ? 'B' : 'A', count);
                QuickHex(t, ptr, count);
-               debugl1(cs, bcs->blog);
+               debugl1(cs, "%s", bcs->blog);
        }
 }
 
index 1df6f9a56ca26926a9e684869e5471cfebc98e82..2be1c8a3bb5f2b7fd84f0d3cd039fb8dc5da3dd0 100644 (file)
@@ -535,7 +535,7 @@ check_arcofi(struct IsdnCardState *cs)
                t = tmp;
                t += sprintf(tmp, "Arcofi data");
                QuickHex(t, p, cs->dc.isac.mon_rxp);
-               debugl1(cs, tmp);
+               debugl1(cs, "%s", tmp);
                if ((cs->dc.isac.mon_rxp == 2) && (cs->dc.isac.mon_rx[0] == 0xa0)) {
                        switch (cs->dc.isac.mon_rx[1]) {
                        case 0x80:
index d4c98d330bfe3223087a3195e25b2e6719ec8065..3f84dd8f1757d8b645af7bf6b3088b7ce084d320 100644 (file)
@@ -344,7 +344,7 @@ static inline void receive_chars(struct IsdnCardState *cs,
 
                t += sprintf(t, "modem read cnt %d", cs->hw.elsa.rcvcnt);
                QuickHex(t, cs->hw.elsa.rcvbuf, cs->hw.elsa.rcvcnt);
-               debugl1(cs, tmp);
+               debugl1(cs, "%s", tmp);
        }
        cs->hw.elsa.rcvcnt = 0;
 }
index 3ccd724ff8c2812eb0af3fae58e6742d16970cd5..497bd026c2378eec6e781df68d007c135be4c1f7 100644 (file)
@@ -901,7 +901,7 @@ Begin:
                                        ptr--;
                                        *ptr++ = '\n';
                                        *ptr = 0;
-                                       HiSax_putstatus(cs, NULL, cs->dlog);
+                                       HiSax_putstatus(cs, NULL, "%s", cs->dlog);
                                } else
                                        HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", total - 3);
                        }
index dc4574f735ef59f24fecbeaf576e58280a56404f..fa1fefd711cde875fbcdf9b56a20f5375f39ced3 100644 (file)
@@ -674,7 +674,7 @@ receive_emsg(struct IsdnCardState *cs)
                                        ptr--;
                                        *ptr++ = '\n';
                                        *ptr = 0;
-                                       HiSax_putstatus(cs, NULL, cs->dlog);
+                                       HiSax_putstatus(cs, NULL, "%s", cs->dlog);
                                } else
                                        HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", skb->len);
                        }
index f398d4838937a3f4eaee68d7dfb2269cbd4ec8c6..a8d6188402c6eacec11ebe4379e1ee9e10dcfe58 100644 (file)
@@ -75,7 +75,7 @@ hscx_empty_fifo(struct BCState *bcs, int count)
                t += sprintf(t, "hscx_empty_fifo %c cnt %d",
                             bcs->hw.hscx.hscx ? 'B' : 'A', count);
                QuickHex(t, ptr, count);
-               debugl1(cs, bcs->blog);
+               debugl1(cs, "%s", bcs->blog);
        }
 }
 
@@ -115,7 +115,7 @@ hscx_fill_fifo(struct BCState *bcs)
                t += sprintf(t, "hscx_fill_fifo %c cnt %d",
                             bcs->hw.hscx.hscx ? 'B' : 'A', count);
                QuickHex(t, ptr, count);
-               debugl1(cs, bcs->blog);
+               debugl1(cs, "%s", bcs->blog);
        }
 }
 
index db5321f6379b0a454ffba83241abf540070138f9..51dae9167238a3ed1ff972508a02f338de6702a0 100644 (file)
@@ -134,7 +134,7 @@ icc_empty_fifo(struct IsdnCardState *cs, int count)
 
                t += sprintf(t, "icc_empty_fifo cnt %d", count);
                QuickHex(t, ptr, count);
-               debugl1(cs, cs->dlog);
+               debugl1(cs, "%s", cs->dlog);
        }
 }
 
@@ -176,7 +176,7 @@ icc_fill_fifo(struct IsdnCardState *cs)
 
                t += sprintf(t, "icc_fill_fifo cnt %d", count);
                QuickHex(t, ptr, count);
-               debugl1(cs, cs->dlog);
+               debugl1(cs, "%s", cs->dlog);
        }
 }
 
index 74feb5c830671340de67784b6f26e2a60251f348..5faa5de24305623bd38bcd4b0047f0063708f172 100644 (file)
@@ -260,7 +260,7 @@ dch_empty_fifo(struct IsdnCardState *cs, int count)
 
                t += sprintf(t, "dch_empty_fifo() cnt %d", count);
                QuickHex(t, ptr, count);
-               debugl1(cs, cs->dlog);
+               debugl1(cs, "%s", cs->dlog);
        }
 }
 
@@ -307,7 +307,7 @@ dch_fill_fifo(struct IsdnCardState *cs)
 
                t += sprintf(t, "dch_fill_fifo() cnt %d", count);
                QuickHex(t, ptr, count);
-               debugl1(cs, cs->dlog);
+               debugl1(cs, "%s", cs->dlog);
        }
 }
 
@@ -539,7 +539,7 @@ bch_empty_fifo(struct BCState *bcs, int count)
 
                t += sprintf(t, "bch_empty_fifo() B-%d cnt %d", hscx, count);
                QuickHex(t, ptr, count);
-               debugl1(cs, bcs->blog);
+               debugl1(cs, "%s", bcs->blog);
        }
 }
 
@@ -582,7 +582,7 @@ bch_fill_fifo(struct BCState *bcs)
 
                t += sprintf(t, "chb_fill_fifo() B-%d cnt %d", hscx, count);
                QuickHex(t, ptr, count);
-               debugl1(cs, bcs->blog);
+               debugl1(cs, "%s", bcs->blog);
        }
 }
 
index a365ccc1c99c886f94df163ab3b60280e20b9b49..7fdf78f4643394a493abb1545a284bf5b6b9bddd 100644 (file)
@@ -137,7 +137,7 @@ isac_empty_fifo(struct IsdnCardState *cs, int count)
 
                t += sprintf(t, "isac_empty_fifo cnt %d", count);
                QuickHex(t, ptr, count);
-               debugl1(cs, cs->dlog);
+               debugl1(cs, "%s", cs->dlog);
        }
 }
 
@@ -179,7 +179,7 @@ isac_fill_fifo(struct IsdnCardState *cs)
 
                t += sprintf(t, "isac_fill_fifo cnt %d", count);
                QuickHex(t, ptr, count);
-               debugl1(cs, cs->dlog);
+               debugl1(cs, "%s", cs->dlog);
        }
 }
 
index 7fdf34704fe5d3469f815f7c44b79f6fb8e15e35..f4956c73aa116de71a99a9ae705c81088f3fbed2 100644 (file)
@@ -74,7 +74,7 @@ sendmsg(struct IsdnCardState *cs, u_char his, u_char creg, u_char len,
                                t = tmp;
                                t += sprintf(t, "sendmbox cnt %d", len);
                                QuickHex(t, &msg[len-i], (i > 64) ? 64 : i);
-                               debugl1(cs, tmp);
+                               debugl1(cs, "%s", tmp);
                                i -= 64;
                        }
                }
@@ -105,7 +105,7 @@ rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u_char *msg)
                                t = tmp;
                                t += sprintf(t, "rcv_mbox cnt %d", ireg->clsb);
                                QuickHex(t, &msg[ireg->clsb - i], (i > 64) ? 64 : i);
-                               debugl1(cs, tmp);
+                               debugl1(cs, "%s", tmp);
                                i -= 64;
                        }
                }
@@ -1248,7 +1248,7 @@ isar_int_main(struct IsdnCardState *cs)
                        tp += sprintf(debbuf, "msg iis(%x) msb(%x)",
                                      ireg->iis, ireg->cmsb);
                        QuickHex(tp, (u_char *)ireg->par, ireg->clsb);
-                       debugl1(cs, debbuf);
+                       debugl1(cs, "%s", debbuf);
                }
                break;
        case ISAR_IIS_INVMSG:
index f946c58d8ab17d86fc8d0242dc25ecc7cbafdb82..e2ae7871a2095ddd8f82f229b8fab14dafd0e6c6 100644 (file)
@@ -81,10 +81,7 @@ modejade(struct BCState *bcs, int mode, int bc)
        int jade = bcs->hw.hscx.hscx;
 
        if (cs->debug & L1_DEB_HSCX) {
-               char tmp[40];
-               sprintf(tmp, "jade %c mode %d ichan %d",
-                       'A' + jade, mode, bc);
-               debugl1(cs, tmp);
+               debugl1(cs, "jade %c mode %d ichan %d", 'A' + jade, mode, bc);
        }
        bcs->mode = mode;
        bcs->channel = bc;
@@ -257,23 +254,18 @@ void
 clear_pending_jade_ints(struct IsdnCardState *cs)
 {
        int val;
-       char tmp[64];
 
        cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0x00);
        cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0x00);
 
        val = cs->BC_Read_Reg(cs, 1, jade_HDLC_ISR);
-       sprintf(tmp, "jade B ISTA %x", val);
-       debugl1(cs, tmp);
+       debugl1(cs, "jade B ISTA %x", val);
        val = cs->BC_Read_Reg(cs, 0, jade_HDLC_ISR);
-       sprintf(tmp, "jade A ISTA %x", val);
-       debugl1(cs, tmp);
+       debugl1(cs, "jade A ISTA %x", val);
        val = cs->BC_Read_Reg(cs, 1, jade_HDLC_STAR);
-       sprintf(tmp, "jade B STAR %x", val);
-       debugl1(cs, tmp);
+       debugl1(cs, "jade B STAR %x", val);
        val = cs->BC_Read_Reg(cs, 0, jade_HDLC_STAR);
-       sprintf(tmp, "jade A STAR %x", val);
-       debugl1(cs, tmp);
+       debugl1(cs, "jade A STAR %x", val);
        /* Unmask ints */
        cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0xF8);
        cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0xF8);
index f521fc83dc766d389c7dc650e9fa1a584024b983..b930da9b5aa685043aca9d8375d31f5bef14020a 100644 (file)
@@ -65,7 +65,7 @@ jade_empty_fifo(struct BCState *bcs, int count)
                t += sprintf(t, "jade_empty_fifo %c cnt %d",
                             bcs->hw.hscx.hscx ? 'B' : 'A', count);
                QuickHex(t, ptr, count);
-               debugl1(cs, bcs->blog);
+               debugl1(cs, "%s", bcs->blog);
        }
 }
 
@@ -105,7 +105,7 @@ jade_fill_fifo(struct BCState *bcs)
                t += sprintf(t, "jade_fill_fifo %c cnt %d",
                             bcs->hw.hscx.hscx ? 'B' : 'A', count);
                QuickHex(t, ptr, count);
-               debugl1(cs, bcs->blog);
+               debugl1(cs, "%s", bcs->blog);
        }
 }
 
index 4c1bca5caa1d0075353cc0451922b8624dd111cb..875402e76d0ad62cf7e400f6da19734998bd6129 100644 (file)
@@ -63,7 +63,7 @@ l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb)
 {
        dev_kfree_skb(skb);
        if (pc->st->l3.debug & L3_DEB_WARN)
-               l3_debug(pc->st, msg);
+               l3_debug(pc->st, "%s", msg);
        l3_1tr6_release_req(pc, 0, NULL);
 }
 
@@ -161,7 +161,6 @@ l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg)
 {
        u_char *p;
        int bcfound = 0;
-       char tmp[80];
        struct sk_buff *skb = arg;
 
        /* Channel Identification */
@@ -214,10 +213,9 @@ l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg)
        /* Signal all services, linklevel takes care of Service-Indicator */
        if (bcfound) {
                if ((pc->para.setup.si1 != 7) && (pc->st->l3.debug & L3_DEB_WARN)) {
-                       sprintf(tmp, "non-digital call: %s -> %s",
+                       l3_debug(pc->st, "non-digital call: %s -> %s",
                                pc->para.setup.phone,
                                pc->para.setup.eazmsn);
-                       l3_debug(pc->st, tmp);
                }
                newl3state(pc, 6);
                pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
@@ -301,7 +299,7 @@ l3_1tr6_info(struct l3_process *pc, u_char pr, void *arg)
 {
        u_char *p;
        int i, tmpcharge = 0;
-       char a_charge[8], tmp[32];
+       char a_charge[8];
        struct sk_buff *skb = arg;
 
        p = skb->data;
@@ -316,8 +314,8 @@ l3_1tr6_info(struct l3_process *pc, u_char pr, void *arg)
                        pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
                }
                if (pc->st->l3.debug & L3_DEB_CHARGE) {
-                       sprintf(tmp, "charging info %d", pc->para.chargeinfo);
-                       l3_debug(pc->st, tmp);
+                       l3_debug(pc->st, "charging info %d",
+                                pc->para.chargeinfo);
                }
        } else if (pc->st->l3.debug & L3_DEB_CHARGE)
                l3_debug(pc->st, "charging info not found");
@@ -399,7 +397,7 @@ l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg)
        struct sk_buff *skb = arg;
        u_char *p;
        int i, tmpcharge = 0;
-       char a_charge[8], tmp[32];
+       char a_charge[8];
 
        StopAllL3Timer(pc);
        p = skb->data;
@@ -414,8 +412,8 @@ l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg)
                        pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
                }
                if (pc->st->l3.debug & L3_DEB_CHARGE) {
-                       sprintf(tmp, "charging info %d", pc->para.chargeinfo);
-                       l3_debug(pc->st, tmp);
+                       l3_debug(pc->st, "charging info %d",
+                                pc->para.chargeinfo);
                }
        } else if (pc->st->l3.debug & L3_DEB_CHARGE)
                l3_debug(pc->st, "charging info not found");
@@ -746,7 +744,6 @@ up1tr6(struct PStack *st, int pr, void *arg)
        int i, mt, cr;
        struct l3_process *proc;
        struct sk_buff *skb = arg;
-       char tmp[80];
 
        switch (pr) {
        case (DL_DATA | INDICATION):
@@ -762,26 +759,23 @@ up1tr6(struct PStack *st, int pr, void *arg)
        }
        if (skb->len < 4) {
                if (st->l3.debug & L3_DEB_PROTERR) {
-                       sprintf(tmp, "up1tr6 len only %d", skb->len);
-                       l3_debug(st, tmp);
+                       l3_debug(st, "up1tr6 len only %d", skb->len);
                }
                dev_kfree_skb(skb);
                return;
        }
        if ((skb->data[0] & 0xfe) != PROTO_DIS_N0) {
                if (st->l3.debug & L3_DEB_PROTERR) {
-                       sprintf(tmp, "up1tr6%sunexpected discriminator %x message len %d",
+                       l3_debug(st, "up1tr6%sunexpected discriminator %x message len %d",
                                (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
                                skb->data[0], skb->len);
-                       l3_debug(st, tmp);
                }
                dev_kfree_skb(skb);
                return;
        }
        if (skb->data[1] != 1) {
                if (st->l3.debug & L3_DEB_PROTERR) {
-                       sprintf(tmp, "up1tr6 CR len not 1");
-                       l3_debug(st, tmp);
+                       l3_debug(st, "up1tr6 CR len not 1");
                }
                dev_kfree_skb(skb);
                return;
@@ -791,9 +785,8 @@ up1tr6(struct PStack *st, int pr, void *arg)
        if (skb->data[0] == PROTO_DIS_N0) {
                dev_kfree_skb(skb);
                if (st->l3.debug & L3_DEB_STATE) {
-                       sprintf(tmp, "up1tr6%s N0 mt %x unhandled",
+                       l3_debug(st, "up1tr6%s N0 mt %x unhandled",
                                (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", mt);
-                       l3_debug(st, tmp);
                }
        } else if (skb->data[0] == PROTO_DIS_N1) {
                if (!(proc = getl3proc(st, cr))) {
@@ -801,8 +794,7 @@ up1tr6(struct PStack *st, int pr, void *arg)
                                if (cr < 128) {
                                        if (!(proc = new_l3_process(st, cr))) {
                                                if (st->l3.debug & L3_DEB_PROTERR) {
-                                                       sprintf(tmp, "up1tr6 no roc mem");
-                                                       l3_debug(st, tmp);
+                                                       l3_debug(st, "up1tr6 no roc mem");
                                                }
                                                dev_kfree_skb(skb);
                                                return;
@@ -821,8 +813,7 @@ up1tr6(struct PStack *st, int pr, void *arg)
                        } else {
                                if (!(proc = new_l3_process(st, cr))) {
                                        if (st->l3.debug & L3_DEB_PROTERR) {
-                                               sprintf(tmp, "up1tr6 no roc mem");
-                                               l3_debug(st, tmp);
+                                               l3_debug(st, "up1tr6 no roc mem");
                                        }
                                        dev_kfree_skb(skb);
                                        return;
@@ -837,18 +828,16 @@ up1tr6(struct PStack *st, int pr, void *arg)
                if (i == ARRAY_SIZE(datastln1)) {
                        dev_kfree_skb(skb);
                        if (st->l3.debug & L3_DEB_STATE) {
-                               sprintf(tmp, "up1tr6%sstate %d mt %x unhandled",
+                               l3_debug(st, "up1tr6%sstate %d mt %x unhandled",
                                        (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
                                        proc->state, mt);
-                               l3_debug(st, tmp);
                        }
                        return;
                } else {
                        if (st->l3.debug & L3_DEB_STATE) {
-                               sprintf(tmp, "up1tr6%sstate %d mt %x",
+                               l3_debug(st, "up1tr6%sstate %d mt %x",
                                        (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
                                        proc->state, mt);
-                               l3_debug(st, tmp);
                        }
                        datastln1[i].rout(proc, pr, skb);
                }
@@ -861,7 +850,6 @@ down1tr6(struct PStack *st, int pr, void *arg)
        int i, cr;
        struct l3_process *proc;
        struct Channel *chan;
-       char tmp[80];
 
        if ((DL_ESTABLISH | REQUEST) == pr) {
                l3_msg(st, pr, NULL);
@@ -888,15 +876,13 @@ down1tr6(struct PStack *st, int pr, void *arg)
                        break;
        if (i == ARRAY_SIZE(downstl)) {
                if (st->l3.debug & L3_DEB_STATE) {
-                       sprintf(tmp, "down1tr6 state %d prim %d unhandled",
+                       l3_debug(st, "down1tr6 state %d prim %d unhandled",
                                proc->state, pr);
-                       l3_debug(st, tmp);
                }
        } else {
                if (st->l3.debug & L3_DEB_STATE) {
-                       sprintf(tmp, "down1tr6 state %d prim %d",
+                       l3_debug(st, "down1tr6 state %d prim %d",
                                proc->state, pr);
-                       l3_debug(st, tmp);
                }
                downstl[i].rout(proc, pr, arg);
        }
index b646eed379dfb52134b828d80c61a74262188168..233e432e06f69ef03e5ae32f56f24ba133a4d249 100644 (file)
@@ -176,7 +176,7 @@ static void printframe(struct IsdnCardState *cs, u_char *buf, int count, char *s
                else
                        j = i;
                QuickHex(t, p, j);
-               debugl1(cs, tmp);
+               debugl1(cs, "%s", tmp);
                p += j;
                i -= j;
                t = tmp;
index 041bf52d9d0acf2a75ec15a702608a269d83d446..af1b020a81f1814eb28b8fea83fca30b3b4332fc 100644 (file)
@@ -1179,7 +1179,7 @@ LogFrame(struct IsdnCardState *cs, u_char *buf, int size)
                dp--;
                *dp++ = '\n';
                *dp = 0;
-               HiSax_putstatus(cs, NULL, cs->dlog);
+               HiSax_putstatus(cs, NULL, "%s", cs->dlog);
        } else
                HiSax_putstatus(cs, "LogFrame: ", "warning Frame too big (%d)", size);
 }
@@ -1246,7 +1246,7 @@ dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir)
        }
        if (finish) {
                *dp = 0;
-               HiSax_putstatus(cs, NULL, cs->dlog);
+               HiSax_putstatus(cs, NULL, "%s", cs->dlog);
                return;
        }
        if ((0xfe & buf[0]) == PROTO_DIS_N0) {  /* 1TR6 */
@@ -1509,5 +1509,5 @@ dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir)
                dp += sprintf(dp, "Unknown protocol %x!", buf[0]);
        }
        *dp = 0;
-       HiSax_putstatus(cs, NULL, cs->dlog);
+       HiSax_putstatus(cs, NULL, "%s", cs->dlog);
 }
index d8cac69358180ee455c92d99a0c58b8203372203..a85895585d906a6367db5cce95b00f031484d05d 100644 (file)
@@ -154,7 +154,7 @@ W6692_empty_fifo(struct IsdnCardState *cs, int count)
 
                t += sprintf(t, "W6692_empty_fifo cnt %d", count);
                QuickHex(t, ptr, count);
-               debugl1(cs, cs->dlog);
+               debugl1(cs, "%s", cs->dlog);
        }
 }
 
@@ -196,7 +196,7 @@ W6692_fill_fifo(struct IsdnCardState *cs)
 
                t += sprintf(t, "W6692_fill_fifo cnt %d", count);
                QuickHex(t, ptr, count);
-               debugl1(cs, cs->dlog);
+               debugl1(cs, "%s", cs->dlog);
        }
 }
 
@@ -226,7 +226,7 @@ W6692B_empty_fifo(struct BCState *bcs, int count)
                t += sprintf(t, "W6692B_empty_fifo %c cnt %d",
                             bcs->channel + '1', count);
                QuickHex(t, ptr, count);
-               debugl1(cs, bcs->blog);
+               debugl1(cs, "%s", bcs->blog);
        }
 }
 
@@ -264,7 +264,7 @@ W6692B_fill_fifo(struct BCState *bcs)
                t += sprintf(t, "W6692B_fill_fifo %c cnt %d",
                             bcs->channel + '1', count);
                QuickHex(t, ptr, count);
-               debugl1(cs, bcs->blog);
+               debugl1(cs, "%s", bcs->blog);
        }
 }
 
index eba380d7b17f18653818bdeedaa9f56386460af1..42d2b893ea67fff1096ce4b7567a247ed194c9c0 100644 (file)
@@ -325,7 +325,6 @@ static int omap2_mbox_remove(struct platform_device *pdev)
        kfree(privblk);
        kfree(mboxblk);
        kfree(list);
-       platform_set_drvdata(pdev, NULL);
 
        return 0;
 }
index b39f6f0b45f27b89f29e580844e41d8d315d9c18..0f12382aa35d6c939b53967b205639134e181eae 100644 (file)
@@ -498,7 +498,7 @@ struct cached_dev {
         */
        atomic_t                has_dirty;
 
-       struct ratelimit        writeback_rate;
+       struct bch_ratelimit    writeback_rate;
        struct delayed_work     writeback_rate_update;
 
        /*
@@ -507,10 +507,9 @@ struct cached_dev {
         */
        sector_t                last_read;
 
-       /* Number of writeback bios in flight */
-       atomic_t                in_flight;
+       /* Limit number of writeback bios in flight */
+       struct semaphore        in_flight;
        struct closure_with_timer writeback;
-       struct closure_waitlist writeback_wait;
 
        struct keybuf           writeback_keys;
 
index 8010eed06a51c8320786a1c49463c98c8aa70555..22d1ae72c2826a53b67656a59ea717a62a3b95a4 100644 (file)
@@ -926,28 +926,45 @@ struct bkey *bch_next_recurse_key(struct btree *b, struct bkey *search)
 
 /* Mergesort */
 
+static void sort_key_next(struct btree_iter *iter,
+                         struct btree_iter_set *i)
+{
+       i->k = bkey_next(i->k);
+
+       if (i->k == i->end)
+               *i = iter->data[--iter->used];
+}
+
 static void btree_sort_fixup(struct btree_iter *iter)
 {
        while (iter->used > 1) {
                struct btree_iter_set *top = iter->data, *i = top + 1;
-               struct bkey *k;
 
                if (iter->used > 2 &&
                    btree_iter_cmp(i[0], i[1]))
                        i++;
 
-               for (k = i->k;
-                    k != i->end && bkey_cmp(top->k, &START_KEY(k)) > 0;
-                    k = bkey_next(k))
-                       if (top->k > i->k)
-                               __bch_cut_front(top->k, k);
-                       else if (KEY_SIZE(k))
-                               bch_cut_back(&START_KEY(k), top->k);
-
-               if (top->k < i->k || k == i->k)
+               if (bkey_cmp(top->k, &START_KEY(i->k)) <= 0)
                        break;
 
-               heap_sift(iter, i - top, btree_iter_cmp);
+               if (!KEY_SIZE(i->k)) {
+                       sort_key_next(iter, i);
+                       heap_sift(iter, i - top, btree_iter_cmp);
+                       continue;
+               }
+
+               if (top->k > i->k) {
+                       if (bkey_cmp(top->k, i->k) >= 0)
+                               sort_key_next(iter, i);
+                       else
+                               bch_cut_front(top->k, i->k);
+
+                       heap_sift(iter, i - top, btree_iter_cmp);
+               } else {
+                       /* can't happen because of comparison func */
+                       BUG_ON(!bkey_cmp(&START_KEY(top->k), &START_KEY(i->k)));
+                       bch_cut_back(&START_KEY(i->k), top->k);
+               }
        }
 }
 
index f9764e61978b5749487862b5ab88eb73b13f18ba..f42fc7ed9cd63b14fd4cf54a879dfd9d046584d1 100644 (file)
@@ -255,7 +255,7 @@ void bch_btree_node_read(struct btree *b)
 
        return;
 err:
-       bch_cache_set_error(b->c, "io error reading bucket %lu",
+       bch_cache_set_error(b->c, "io error reading bucket %zu",
                            PTR_BUCKET_NR(b->c, &b->key, 0));
 }
 
@@ -612,7 +612,7 @@ static unsigned long bch_mca_scan(struct shrinker *shrink,
                return SHRINK_STOP;
 
        /* Return -1 if we can't do anything right now */
-       if (sc->gfp_mask & __GFP_WAIT)
+       if (sc->gfp_mask & __GFP_IO)
                mutex_lock(&c->bucket_lock);
        else if (!mutex_trylock(&c->bucket_lock))
                return -1;
index ba95ab84b2be5a5a32292625d229bb29e051a53d..8435f81e5d858012e8aca6be8204e923a34b1d01 100644 (file)
@@ -153,7 +153,8 @@ int bch_journal_read(struct cache_set *c, struct list_head *list,
                bitmap_zero(bitmap, SB_JOURNAL_BUCKETS);
                pr_debug("%u journal buckets", ca->sb.njournal_buckets);
 
-               /* Read journal buckets ordered by golden ratio hash to quickly
+               /*
+                * Read journal buckets ordered by golden ratio hash to quickly
                 * find a sequence of buckets with valid journal entries
                 */
                for (i = 0; i < ca->sb.njournal_buckets; i++) {
@@ -166,18 +167,20 @@ int bch_journal_read(struct cache_set *c, struct list_head *list,
                                goto bsearch;
                }
 
-               /* If that fails, check all the buckets we haven't checked
+               /*
+                * If that fails, check all the buckets we haven't checked
                 * already
                 */
                pr_debug("falling back to linear search");
 
-               for (l = 0; l < ca->sb.njournal_buckets; l++) {
-                       if (test_bit(l, bitmap))
-                               continue;
-
+               for (l = find_first_zero_bit(bitmap, ca->sb.njournal_buckets);
+                    l < ca->sb.njournal_buckets;
+                    l = find_next_zero_bit(bitmap, ca->sb.njournal_buckets, l + 1))
                        if (read_bucket(l))
                                goto bsearch;
-               }
+
+               if (list_empty(list))
+                       continue;
 bsearch:
                /* Binary search */
                m = r = find_next_bit(bitmap, ca->sb.njournal_buckets, l + 1);
@@ -197,10 +200,12 @@ bsearch:
                                r = m;
                }
 
-               /* Read buckets in reverse order until we stop finding more
+               /*
+                * Read buckets in reverse order until we stop finding more
                 * journal entries
                 */
-               pr_debug("finishing up");
+               pr_debug("finishing up: m %u njournal_buckets %u",
+                        m, ca->sb.njournal_buckets);
                l = m;
 
                while (1) {
@@ -228,9 +233,10 @@ bsearch:
                        }
        }
 
-       c->journal.seq = list_entry(list->prev,
-                                   struct journal_replay,
-                                   list)->j.seq;
+       if (!list_empty(list))
+               c->journal.seq = list_entry(list->prev,
+                                           struct journal_replay,
+                                           list)->j.seq;
 
        return 0;
 #undef read_bucket
@@ -428,7 +434,7 @@ static void do_journal_discard(struct cache *ca)
                return;
        }
 
-       switch (atomic_read(&ja->discard_in_flight) == DISCARD_IN_FLIGHT) {
+       switch (atomic_read(&ja->discard_in_flight)) {
        case DISCARD_IN_FLIGHT:
                return;
 
@@ -689,6 +695,7 @@ void bch_journal_meta(struct cache_set *c, struct closure *cl)
                if (cl)
                        BUG_ON(!closure_wait(&w->wait, cl));
 
+               closure_flush(&c->journal.io);
                __journal_try_write(c, true);
        }
 }
index 786a1a4f74d853fafe3ab2ae263d2ecf780134aa..71eb233b9ace7a23f143170e8f4cc924a2a1de9a 100644 (file)
@@ -997,14 +997,17 @@ static void request_write(struct cached_dev *dc, struct search *s)
        } else {
                bch_writeback_add(dc);
 
-               if (s->op.flush_journal) {
+               if (bio->bi_rw & REQ_FLUSH) {
                        /* Also need to send a flush to the backing device */
-                       s->op.cache_bio = bio_clone_bioset(bio, GFP_NOIO,
-                                                          dc->disk.bio_split);
+                       struct bio *flush = bio_alloc_bioset(0, GFP_NOIO,
+                                                            dc->disk.bio_split);
 
-                       bio->bi_size = 0;
-                       bio->bi_vcnt = 0;
-                       closure_bio_submit(bio, cl, s->d);
+                       flush->bi_rw    = WRITE_FLUSH;
+                       flush->bi_bdev  = bio->bi_bdev;
+                       flush->bi_end_io = request_endio;
+                       flush->bi_private = cl;
+
+                       closure_bio_submit(flush, cl, s->d);
                } else {
                        s->op.cache_bio = bio;
                }
index 4fe6ab2fbe2ede59644441521aa4cc2f27f5d312..924dcfdae11102256e1ce193eefc01d82cc173cc 100644 (file)
@@ -223,8 +223,13 @@ STORE(__cached_dev)
        }
 
        if (attr == &sysfs_label) {
-               /* note: endlines are preserved */
-               memcpy(dc->sb.label, buf, SB_LABEL_SIZE);
+               if (size > SB_LABEL_SIZE)
+                       return -EINVAL;
+               memcpy(dc->sb.label, buf, size);
+               if (size < SB_LABEL_SIZE)
+                       dc->sb.label[size] = '\0';
+               if (size && dc->sb.label[size - 1] == '\n')
+                       dc->sb.label[size - 1] = '\0';
                bch_write_bdev_super(dc, NULL);
                if (dc->disk.c) {
                        memcpy(dc->disk.c->uuids[dc->disk.id].label,
index 98eb81159a22ba9f9e88fec53127e2e338ae3d4d..420dad545c7d8a01e8b5c18d26db4b25677fd334 100644 (file)
@@ -190,7 +190,16 @@ void bch_time_stats_update(struct time_stats *stats, uint64_t start_time)
        stats->last = now ?: 1;
 }
 
-unsigned bch_next_delay(struct ratelimit *d, uint64_t done)
+/**
+ * bch_next_delay() - increment @d by the amount of work done, and return how
+ * long to delay until the next time to do some work.
+ *
+ * @d - the struct bch_ratelimit to update
+ * @done - the amount of work done, in arbitrary units
+ *
+ * Returns the amount of time to delay by, in jiffies
+ */
+uint64_t bch_next_delay(struct bch_ratelimit *d, uint64_t done)
 {
        uint64_t now = local_clock();
 
index 1ae2a73ad85f5628b5292b769d79b0f28252f4ca..ea345c6896f47777942b64f88810c99d4cbc278e 100644 (file)
@@ -450,17 +450,23 @@ read_attribute(name ## _last_ ## frequency_units)
        (ewma) >> factor;                                               \
 })
 
-struct ratelimit {
+struct bch_ratelimit {
+       /* Next time we want to do some work, in nanoseconds */
        uint64_t                next;
+
+       /*
+        * Rate at which we want to do work, in units per nanosecond
+        * The units here correspond to the units passed to bch_next_delay()
+        */
        unsigned                rate;
 };
 
-static inline void ratelimit_reset(struct ratelimit *d)
+static inline void bch_ratelimit_reset(struct bch_ratelimit *d)
 {
        d->next = local_clock();
 }
 
-unsigned bch_next_delay(struct ratelimit *d, uint64_t done);
+uint64_t bch_next_delay(struct bch_ratelimit *d, uint64_t done);
 
 #define __DIV_SAFE(n, d, zero)                                         \
 ({                                                                     \
index 22cbff551628f3c9cff87ccc35563c09974f03b3..ba3ee48320f2a38509adb2603f766c55e67f1da1 100644 (file)
@@ -94,11 +94,15 @@ static void update_writeback_rate(struct work_struct *work)
 
 static unsigned writeback_delay(struct cached_dev *dc, unsigned sectors)
 {
+       uint64_t ret;
+
        if (atomic_read(&dc->disk.detaching) ||
            !dc->writeback_percent)
                return 0;
 
-       return bch_next_delay(&dc->writeback_rate, sectors * 10000000ULL);
+       ret = bch_next_delay(&dc->writeback_rate, sectors * 10000000ULL);
+
+       return min_t(uint64_t, ret, HZ);
 }
 
 /* Background writeback */
@@ -208,7 +212,7 @@ normal_refill:
 
        up_write(&dc->writeback_lock);
 
-       ratelimit_reset(&dc->writeback_rate);
+       bch_ratelimit_reset(&dc->writeback_rate);
 
        /* Punt to workqueue only so we don't recurse and blow the stack */
        continue_at(cl, read_dirty, dirty_wq);
@@ -318,9 +322,7 @@ static void write_dirty_finish(struct closure *cl)
        }
 
        bch_keybuf_del(&dc->writeback_keys, w);
-       atomic_dec_bug(&dc->in_flight);
-
-       closure_wake_up(&dc->writeback_wait);
+       up(&dc->in_flight);
 
        closure_return_with_destructor(cl, dirty_io_destructor);
 }
@@ -349,7 +351,7 @@ static void write_dirty(struct closure *cl)
 
        closure_bio_submit(&io->bio, cl, &io->dc->disk);
 
-       continue_at(cl, write_dirty_finish, dirty_wq);
+       continue_at(cl, write_dirty_finish, system_wq);
 }
 
 static void read_dirty_endio(struct bio *bio, int error)
@@ -369,7 +371,7 @@ static void read_dirty_submit(struct closure *cl)
 
        closure_bio_submit(&io->bio, cl, &io->dc->disk);
 
-       continue_at(cl, write_dirty, dirty_wq);
+       continue_at(cl, write_dirty, system_wq);
 }
 
 static void read_dirty(struct closure *cl)
@@ -394,12 +396,8 @@ static void read_dirty(struct closure *cl)
 
                if (delay > 0 &&
                    (KEY_START(&w->key) != dc->last_read ||
-                    jiffies_to_msecs(delay) > 50)) {
-                       w->private = NULL;
-
-                       closure_delay(&dc->writeback, delay);
-                       continue_at(cl, read_dirty, dirty_wq);
-               }
+                    jiffies_to_msecs(delay) > 50))
+                       delay = schedule_timeout_uninterruptible(delay);
 
                dc->last_read   = KEY_OFFSET(&w->key);
 
@@ -424,15 +422,10 @@ static void read_dirty(struct closure *cl)
 
                trace_bcache_writeback(&w->key);
 
-               closure_call(&io->cl, read_dirty_submit, NULL, &dc->disk.cl);
+               down(&dc->in_flight);
+               closure_call(&io->cl, read_dirty_submit, NULL, cl);
 
                delay = writeback_delay(dc, KEY_SIZE(&w->key));
-
-               atomic_inc(&dc->in_flight);
-
-               if (!closure_wait_event(&dc->writeback_wait, cl,
-                                       atomic_read(&dc->in_flight) < 64))
-                       continue_at(cl, read_dirty, dirty_wq);
        }
 
        if (0) {
@@ -442,7 +435,11 @@ err:
                bch_keybuf_del(&dc->writeback_keys, w);
        }
 
-       refill_dirty(cl);
+       /*
+        * Wait for outstanding writeback IOs to finish (and keybuf slots to be
+        * freed) before refilling again
+        */
+       continue_at(cl, refill_dirty, dirty_wq);
 }
 
 /* Init */
@@ -484,6 +481,7 @@ void bch_sectors_dirty_init(struct cached_dev *dc)
 
 void bch_cached_dev_writeback_init(struct cached_dev *dc)
 {
+       sema_init(&dc->in_flight, 64);
        closure_init_unlocked(&dc->writeback);
        init_rwsem(&dc->writeback_lock);
 
@@ -513,7 +511,7 @@ void bch_writeback_exit(void)
 
 int __init bch_writeback_init(void)
 {
-       dirty_wq = create_singlethread_workqueue("bcache_writeback");
+       dirty_wq = create_workqueue("bcache_writeback");
        if (!dirty_wq)
                return -ENOMEM;
 
index ea49834377c8e17b6e8b221e4bd58389a8d7c32e..2a20986a2fec9701cd25e443c990f2b7a8479f9f 100644 (file)
@@ -19,8 +19,6 @@
 #define DM_MSG_PREFIX "io"
 
 #define DM_IO_MAX_REGIONS      BITS_PER_LONG
-#define MIN_IOS                16
-#define MIN_BIOS       16
 
 struct dm_io_client {
        mempool_t *pool;
@@ -50,16 +48,17 @@ static struct kmem_cache *_dm_io_cache;
 struct dm_io_client *dm_io_client_create(void)
 {
        struct dm_io_client *client;
+       unsigned min_ios = dm_get_reserved_bio_based_ios();
 
        client = kmalloc(sizeof(*client), GFP_KERNEL);
        if (!client)
                return ERR_PTR(-ENOMEM);
 
-       client->pool = mempool_create_slab_pool(MIN_IOS, _dm_io_cache);
+       client->pool = mempool_create_slab_pool(min_ios, _dm_io_cache);
        if (!client->pool)
                goto bad;
 
-       client->bios = bioset_create(MIN_BIOS, 0);
+       client->bios = bioset_create(min_ios, 0);
        if (!client->bios)
                goto bad;
 
index b759a127f9c3718bbfffe2d16ca258fe4afe15e2..de570a55876451a0326d071da4cf68fd772eec2e 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/device-mapper.h>
 
+#include "dm.h"
 #include "dm-path-selector.h"
 #include "dm-uevent.h"
 
@@ -116,8 +117,6 @@ struct dm_mpath_io {
 
 typedef int (*action_fn) (struct pgpath *pgpath);
 
-#define MIN_IOS 256    /* Mempool size */
-
 static struct kmem_cache *_mpio_cache;
 
 static struct workqueue_struct *kmultipathd, *kmpath_handlerd;
@@ -190,6 +189,7 @@ static void free_priority_group(struct priority_group *pg,
 static struct multipath *alloc_multipath(struct dm_target *ti)
 {
        struct multipath *m;
+       unsigned min_ios = dm_get_reserved_rq_based_ios();
 
        m = kzalloc(sizeof(*m), GFP_KERNEL);
        if (m) {
@@ -202,7 +202,7 @@ static struct multipath *alloc_multipath(struct dm_target *ti)
                INIT_WORK(&m->trigger_event, trigger_event);
                init_waitqueue_head(&m->pg_init_wait);
                mutex_init(&m->work_mutex);
-               m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache);
+               m->mpio_pool = mempool_create_slab_pool(min_ios, _mpio_cache);
                if (!m->mpio_pool) {
                        kfree(m);
                        return NULL;
@@ -1268,6 +1268,7 @@ static int noretry_error(int error)
        case -EREMOTEIO:
        case -EILSEQ:
        case -ENODATA:
+       case -ENOSPC:
                return 1;
        }
 
@@ -1298,8 +1299,17 @@ static int do_end_io(struct multipath *m, struct request *clone,
        if (!error && !clone->errors)
                return 0;       /* I/O complete */
 
-       if (noretry_error(error))
+       if (noretry_error(error)) {
+               if ((clone->cmd_flags & REQ_WRITE_SAME) &&
+                   !clone->q->limits.max_write_same_sectors) {
+                       struct queue_limits *limits;
+
+                       /* device doesn't really support WRITE SAME, disable it */
+                       limits = dm_get_queue_limits(dm_table_get_md(m->ti->table));
+                       limits->max_write_same_sectors = 0;
+               }
                return error;
+       }
 
        if (mpio->pgpath)
                fail_path(mpio->pgpath);
index 3ac415675b6c778b5dd22aaaf4ee6c2dc4ca48eb..4caa8e6d59d7968584e23a9187bc07f8c81df321 100644 (file)
@@ -256,7 +256,7 @@ static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, int rw,
         */
        INIT_WORK_ONSTACK(&req.work, do_metadata);
        queue_work(ps->metadata_wq, &req.work);
-       flush_work(&req.work);
+       flush_workqueue(ps->metadata_wq);
 
        return req.result;
 }
index c434e5aab2dfc9e6a63ca7700e5ac1c1deacd025..aec57d76db5d616c8e692fa95cee58a8f62a0573 100644 (file)
@@ -725,17 +725,16 @@ static int calc_max_buckets(void)
  */
 static int init_hash_tables(struct dm_snapshot *s)
 {
-       sector_t hash_size, cow_dev_size, origin_dev_size, max_buckets;
+       sector_t hash_size, cow_dev_size, max_buckets;
 
        /*
         * Calculate based on the size of the original volume or
         * the COW volume...
         */
        cow_dev_size = get_dev_size(s->cow->bdev);
-       origin_dev_size = get_dev_size(s->origin->bdev);
        max_buckets = calc_max_buckets();
 
-       hash_size = min(origin_dev_size, cow_dev_size) >> s->store->chunk_shift;
+       hash_size = cow_dev_size >> s->store->chunk_shift;
        hash_size = min(hash_size, max_buckets);
 
        if (hash_size < 64)
index 8ae31e8d3d64964652fd1bd8d31d35d3ed49e879..3d404c1371ed2d7e6f4fa052fd4379fbc89ec388 100644 (file)
@@ -451,19 +451,26 @@ static void dm_stat_for_entry(struct dm_stat *s, size_t entry,
        struct dm_stat_percpu *p;
 
        /*
-        * For strict correctness we should use local_irq_disable/enable
+        * For strict correctness we should use local_irq_save/restore
         * instead of preempt_disable/enable.
         *
-        * This is racy if the driver finishes bios from non-interrupt
-        * context as well as from interrupt context or from more different
-        * interrupts.
+        * preempt_disable/enable is racy if the driver finishes bios
+        * from non-interrupt context as well as from interrupt context
+        * or from more different interrupts.
         *
-        * However, the race only results in not counting some events,
-        * so it is acceptable.
+        * On 64-bit architectures the race only results in not counting some
+        * events, so it is acceptable.  On 32-bit architectures the race could
+        * cause the counter going off by 2^32, so we need to do proper locking
+        * there.
         *
         * part_stat_lock()/part_stat_unlock() have this race too.
         */
+#if BITS_PER_LONG == 32
+       unsigned long flags;
+       local_irq_save(flags);
+#else
        preempt_disable();
+#endif
        p = &s->stat_percpu[smp_processor_id()][entry];
 
        if (!end) {
@@ -478,7 +485,11 @@ static void dm_stat_for_entry(struct dm_stat *s, size_t entry,
                p->ticks[idx] += duration;
        }
 
+#if BITS_PER_LONG == 32
+       local_irq_restore(flags);
+#else
        preempt_enable();
+#endif
 }
 
 static void __dm_stat_bio(struct dm_stat *s, unsigned long bi_rw,
index ed063427d676f64b53f3d9569449fc0daaf174b0..2c0cf511ec2385fa5a558b5d2e1e1ed0c874c9f6 100644 (file)
@@ -2095,6 +2095,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
         * them down to the data device.  The thin device's discard
         * processing will cause mappings to be removed from the btree.
         */
+       ti->discard_zeroes_data_unsupported = true;
        if (pf.discard_enabled && pf.discard_passdown) {
                ti->num_discard_bios = 1;
 
@@ -2104,7 +2105,6 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
                 * thin devices' discard limits consistent).
                 */
                ti->discards_supported = true;
-               ti->discard_zeroes_data_unsupported = true;
        }
        ti->private = pt;
 
@@ -2689,8 +2689,16 @@ static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
         * They get transferred to the live pool in bind_control_target()
         * called from pool_preresume().
         */
-       if (!pt->adjusted_pf.discard_enabled)
+       if (!pt->adjusted_pf.discard_enabled) {
+               /*
+                * Must explicitly disallow stacking discard limits otherwise the
+                * block layer will stack them if pool's data device has support.
+                * QUEUE_FLAG_DISCARD wouldn't be set but there is no way for the
+                * user to see that, so make sure to set all discard limits to 0.
+                */
+               limits->discard_granularity = 0;
                return;
+       }
 
        disable_passdown_if_not_supported(pt);
 
@@ -2826,10 +2834,10 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
        ti->per_bio_data_size = sizeof(struct dm_thin_endio_hook);
 
        /* In case the pool supports discards, pass them on. */
+       ti->discard_zeroes_data_unsupported = true;
        if (tc->pool->pf.discard_enabled) {
                ti->discards_supported = true;
                ti->num_discard_bios = 1;
-               ti->discard_zeroes_data_unsupported = true;
                /* Discard bios must be split on a block boundary */
                ti->split_discard_bios = true;
        }
index 6a5e9ed2fcc3eb775268e2e5fc401efa55d6da3d..b3e26c7d141771c74d24726f8b5a56ea2134b156 100644 (file)
@@ -211,10 +211,55 @@ struct dm_md_mempools {
        struct bio_set *bs;
 };
 
-#define MIN_IOS 256
+#define RESERVED_BIO_BASED_IOS         16
+#define RESERVED_REQUEST_BASED_IOS     256
+#define RESERVED_MAX_IOS               1024
 static struct kmem_cache *_io_cache;
 static struct kmem_cache *_rq_tio_cache;
 
+/*
+ * Bio-based DM's mempools' reserved IOs set by the user.
+ */
+static unsigned reserved_bio_based_ios = RESERVED_BIO_BASED_IOS;
+
+/*
+ * Request-based DM's mempools' reserved IOs set by the user.
+ */
+static unsigned reserved_rq_based_ios = RESERVED_REQUEST_BASED_IOS;
+
+static unsigned __dm_get_reserved_ios(unsigned *reserved_ios,
+                                     unsigned def, unsigned max)
+{
+       unsigned ios = ACCESS_ONCE(*reserved_ios);
+       unsigned modified_ios = 0;
+
+       if (!ios)
+               modified_ios = def;
+       else if (ios > max)
+               modified_ios = max;
+
+       if (modified_ios) {
+               (void)cmpxchg(reserved_ios, ios, modified_ios);
+               ios = modified_ios;
+       }
+
+       return ios;
+}
+
+unsigned dm_get_reserved_bio_based_ios(void)
+{
+       return __dm_get_reserved_ios(&reserved_bio_based_ios,
+                                    RESERVED_BIO_BASED_IOS, RESERVED_MAX_IOS);
+}
+EXPORT_SYMBOL_GPL(dm_get_reserved_bio_based_ios);
+
+unsigned dm_get_reserved_rq_based_ios(void)
+{
+       return __dm_get_reserved_ios(&reserved_rq_based_ios,
+                                    RESERVED_REQUEST_BASED_IOS, RESERVED_MAX_IOS);
+}
+EXPORT_SYMBOL_GPL(dm_get_reserved_rq_based_ios);
+
 static int __init local_init(void)
 {
        int r = -ENOMEM;
@@ -2277,6 +2322,17 @@ struct target_type *dm_get_immutable_target_type(struct mapped_device *md)
        return md->immutable_target_type;
 }
 
+/*
+ * The queue_limits are only valid as long as you have a reference
+ * count on 'md'.
+ */
+struct queue_limits *dm_get_queue_limits(struct mapped_device *md)
+{
+       BUG_ON(!atomic_read(&md->holders));
+       return &md->queue->limits;
+}
+EXPORT_SYMBOL_GPL(dm_get_queue_limits);
+
 /*
  * Fully initialize a request-based queue (->elevator, ->request_fn, etc).
  */
@@ -2862,18 +2918,18 @@ struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity, u
 
        if (type == DM_TYPE_BIO_BASED) {
                cachep = _io_cache;
-               pool_size = 16;
+               pool_size = dm_get_reserved_bio_based_ios();
                front_pad = roundup(per_bio_data_size, __alignof__(struct dm_target_io)) + offsetof(struct dm_target_io, clone);
        } else if (type == DM_TYPE_REQUEST_BASED) {
                cachep = _rq_tio_cache;
-               pool_size = MIN_IOS;
+               pool_size = dm_get_reserved_rq_based_ios();
                front_pad = offsetof(struct dm_rq_clone_bio_info, clone);
                /* per_bio_data_size is not used. See __bind_mempools(). */
                WARN_ON(per_bio_data_size != 0);
        } else
                goto out;
 
-       pools->io_pool = mempool_create_slab_pool(MIN_IOS, cachep);
+       pools->io_pool = mempool_create_slab_pool(pool_size, cachep);
        if (!pools->io_pool)
                goto out;
 
@@ -2924,6 +2980,13 @@ module_exit(dm_exit);
 
 module_param(major, uint, 0);
 MODULE_PARM_DESC(major, "The major number of the device mapper");
+
+module_param(reserved_bio_based_ios, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(reserved_bio_based_ios, "Reserved IOs in bio-based mempools");
+
+module_param(reserved_rq_based_ios, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(reserved_rq_based_ios, "Reserved IOs in request-based mempools");
+
 MODULE_DESCRIPTION(DM_NAME " driver");
 MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
 MODULE_LICENSE("GPL");
index 5e604cc7b4aa26c41db96c84c1fa0f306bcb698e..1d1ad7b7e527e671d1265007b25e2e04217509ab 100644 (file)
@@ -184,6 +184,9 @@ void dm_free_md_mempools(struct dm_md_mempools *pools);
 /*
  * Helpers that are used by DM core
  */
+unsigned dm_get_reserved_bio_based_ios(void);
+unsigned dm_get_reserved_rq_based_ios(void);
+
 static inline bool dm_message_test_buffer_overflow(char *result, unsigned maxlen)
 {
        return !maxlen || strlen(result) + 1 >= maxlen;
index df3a0ec7fd2c68f83bf2d287efd7a75378766980..1c3608039663e281d23541f17aedcbce044c87fb 100644 (file)
@@ -2182,9 +2182,9 @@ static int isp_probe(struct platform_device *pdev)
        isp->pdata = pdata;
        isp->ref_count = 0;
 
-       isp->raw_dmamask = DMA_BIT_MASK(32);
-       isp->dev->dma_mask = &isp->raw_dmamask;
-       isp->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(isp->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        platform_set_drvdata(pdev, isp);
 
index cd3eff45ae7d50d0a8b28f4cf5c95dab80abb913..ce65d3ae1aa7b8070f5161bad3caf9d4581b1cb9 100644 (file)
@@ -152,7 +152,6 @@ struct isp_xclk {
  * @mmio_base_phys: Array with physical L4 bus addresses for ISP register
  *                  regions.
  * @mmio_size: Array with ISP register regions size in bytes.
- * @raw_dmamask: Raw DMA mask
  * @stat_lock: Spinlock for handling statistics
  * @isp_mutex: Mutex for serializing requests to ISP.
  * @crashed: Bitmask of crashed entities (indexed by entity ID)
@@ -190,8 +189,6 @@ struct isp_device {
        unsigned long mmio_base_phys[OMAP3_ISP_IOMEM_LAST];
        resource_size_t mmio_size[OMAP3_ISP_IOMEM_LAST];
 
-       u64 raw_dmamask;
-
        /* ISP Obj */
        spinlock_t stat_lock;   /* common lock for statistic drivers */
        struct mutex isp_mutex; /* For handling ref_count field */
index d0fdc134068a05ed9967fe98ca7d9a6d6429e710..f6ff711aa5bbbaa4a177dbd416ccdab53017bb23 100644 (file)
@@ -57,6 +57,7 @@ void mei_amthif_reset_params(struct mei_device *dev)
        dev->iamthif_ioctl = false;
        dev->iamthif_state = MEI_IAMTHIF_IDLE;
        dev->iamthif_timer = 0;
+       dev->iamthif_stall_timer = 0;
 }
 
 /**
index 6d0282c08a06cdbe6233a379ee575882b1d7a525..cd2033cd7120d7631fa8d345409ed9ea86259799 100644 (file)
@@ -297,10 +297,13 @@ int __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
 
        if (cl->reading_state != MEI_READ_COMPLETE &&
            !waitqueue_active(&cl->rx_wait)) {
+
                mutex_unlock(&dev->device_lock);
 
                if (wait_event_interruptible(cl->rx_wait,
-                               (MEI_READ_COMPLETE == cl->reading_state))) {
+                               cl->reading_state == MEI_READ_COMPLETE  ||
+                               mei_cl_is_transitioning(cl))) {
+
                        if (signal_pending(current))
                                return -EINTR;
                        return -ERESTARTSYS;
index 9eb031e920701e8ad8feadf3bec2900b182e4a5c..892cc4207fa202629e27698c0ae536f0b81880b0 100644 (file)
@@ -90,6 +90,12 @@ static inline bool mei_cl_is_connected(struct mei_cl *cl)
                cl->dev->dev_state == MEI_DEV_ENABLED &&
                cl->state == MEI_FILE_CONNECTED);
 }
+static inline bool mei_cl_is_transitioning(struct mei_cl *cl)
+{
+       return (MEI_FILE_INITIALIZING == cl->state ||
+               MEI_FILE_DISCONNECTED == cl->state ||
+               MEI_FILE_DISCONNECTING == cl->state);
+}
 
 bool mei_cl_is_other_connecting(struct mei_cl *cl);
 int mei_cl_disconnect(struct mei_cl *cl);
index 6127ab64bb399323e57e418e9742c2f5b8a9d86d..0a0448326e9d583f951932b220d90186c59f92b7 100644 (file)
@@ -35,11 +35,15 @@ static void mei_hbm_me_cl_allocate(struct mei_device *dev)
        struct mei_me_client *clients;
        int b;
 
+       dev->me_clients_num = 0;
+       dev->me_client_presentation_num = 0;
+       dev->me_client_index = 0;
+
        /* count how many ME clients we have */
        for_each_set_bit(b, dev->me_clients_map, MEI_CLIENTS_MAX)
                dev->me_clients_num++;
 
-       if (dev->me_clients_num <= 0)
+       if (dev->me_clients_num == 0)
                return;
 
        kfree(dev->me_clients);
@@ -221,7 +225,7 @@ static int mei_hbm_prop_req(struct mei_device *dev)
        struct hbm_props_request *prop_req;
        const size_t len = sizeof(struct hbm_props_request);
        unsigned long next_client_index;
-       u8 client_num;
+       unsigned long client_num;
 
 
        client_num = dev->me_client_presentation_num;
@@ -677,8 +681,6 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
                if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
                    dev->hbm_state == MEI_HBM_ENUM_CLIENTS) {
                                dev->init_clients_timer = 0;
-                               dev->me_client_presentation_num = 0;
-                               dev->me_client_index = 0;
                                mei_hbm_me_cl_allocate(dev);
                                dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES;
 
index 92c73118b13c450149e21ec48b990e6329f4e5b1..6197018e2f16a24296619442fe6c8744c7c55b88 100644 (file)
@@ -175,6 +175,9 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
                memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg));
        }
 
+       /* we're already in reset, cancel the init timer */
+       dev->init_clients_timer = 0;
+
        dev->me_clients_num = 0;
        dev->rd_msg_hdr = 0;
        dev->wd_pending = false;
index 173ff095be0dd6747145c9653726b3e00f85cd81..cabeddd66c1f406f73f7e5bed2a56b7e52cd7621 100644 (file)
@@ -249,19 +249,16 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
                mutex_unlock(&dev->device_lock);
 
                if (wait_event_interruptible(cl->rx_wait,
-                       (MEI_READ_COMPLETE == cl->reading_state ||
-                        MEI_FILE_INITIALIZING == cl->state ||
-                        MEI_FILE_DISCONNECTED == cl->state ||
-                        MEI_FILE_DISCONNECTING == cl->state))) {
+                               MEI_READ_COMPLETE == cl->reading_state ||
+                               mei_cl_is_transitioning(cl))) {
+
                        if (signal_pending(current))
                                return -EINTR;
                        return -ERESTARTSYS;
                }
 
                mutex_lock(&dev->device_lock);
-               if (MEI_FILE_INITIALIZING == cl->state ||
-                   MEI_FILE_DISCONNECTED == cl->state ||
-                   MEI_FILE_DISCONNECTING == cl->state) {
+               if (mei_cl_is_transitioning(cl)) {
                        rets = -EBUSY;
                        goto out;
                }
index 7b918b2fb89468ad6c653a3ff9e0f616aefa5022..456b322013e269fc61f911d6f5761768c2863d4f 100644 (file)
@@ -396,9 +396,9 @@ struct mei_device {
        struct mei_me_client *me_clients; /* Note: memory has to be allocated */
        DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX);
        DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX);
-       u8 me_clients_num;
-       u8 me_client_presentation_num;
-       u8 me_client_index;
+       unsigned long me_clients_num;
+       unsigned long me_client_presentation_num;
+       unsigned long me_client_index;
 
        struct mei_cl wd_cl;
        enum mei_wd_states wd_state;
index fa9632eb63f14cc9af971f290989f13263c3cbfd..357bbc54fe4b6f423aa2dcc86ca3a23624748a6b 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/freezer.h>
 #include <linux/kthread.h>
 #include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -196,7 +197,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
        struct mmc_queue_req *mqrq_prev = &mq->mqrq[1];
 
        if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
-               limit = *mmc_dev(host)->dma_mask;
+               limit = dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
 
        mq->card = card;
        mq->queue = blk_init_queue(mmc_request_fn, lock);
index c3785edc0e92c851d3c36a0481a1b2936f92fc63..d135c76c4855b825175370e215979bd528e4b2d4 100644 (file)
@@ -62,6 +62,7 @@ static unsigned int fmax = 515633;
  * @signal_direction: input/out direction of bus signals can be indicated
  * @pwrreg_clkgate: MMCIPOWER register must be used to gate the clock
  * @busy_detect: true if busy detection on dat0 is supported
+ * @pwrreg_nopower: bits in MMCIPOWER don't controls ext. power supply
  */
 struct variant_data {
        unsigned int            clkreg;
@@ -76,6 +77,7 @@ struct variant_data {
        bool                    signal_direction;
        bool                    pwrreg_clkgate;
        bool                    busy_detect;
+       bool                    pwrreg_nopower;
 };
 
 static struct variant_data variant_arm = {
@@ -109,6 +111,7 @@ static struct variant_data variant_u300 = {
        .pwrreg_powerup         = MCI_PWR_ON,
        .signal_direction       = true,
        .pwrreg_clkgate         = true,
+       .pwrreg_nopower         = true,
 };
 
 static struct variant_data variant_nomadik = {
@@ -121,6 +124,7 @@ static struct variant_data variant_nomadik = {
        .pwrreg_powerup         = MCI_PWR_ON,
        .signal_direction       = true,
        .pwrreg_clkgate         = true,
+       .pwrreg_nopower         = true,
 };
 
 static struct variant_data variant_ux500 = {
@@ -135,6 +139,7 @@ static struct variant_data variant_ux500 = {
        .signal_direction       = true,
        .pwrreg_clkgate         = true,
        .busy_detect            = true,
+       .pwrreg_nopower         = true,
 };
 
 static struct variant_data variant_ux500v2 = {
@@ -150,6 +155,7 @@ static struct variant_data variant_ux500v2 = {
        .signal_direction       = true,
        .pwrreg_clkgate         = true,
        .busy_detect            = true,
+       .pwrreg_nopower         = true,
 };
 
 static int mmci_card_busy(struct mmc_host *mmc)
@@ -189,6 +195,21 @@ static int mmci_validate_data(struct mmci_host *host,
        return 0;
 }
 
+static void mmci_reg_delay(struct mmci_host *host)
+{
+       /*
+        * According to the spec, at least three feedback clock cycles
+        * of max 52 MHz must pass between two writes to the MMCICLOCK reg.
+        * Three MCLK clock cycles must pass between two MMCIPOWER reg writes.
+        * Worst delay time during card init is at 100 kHz => 30 us.
+        * Worst delay time when up and running is at 25 MHz => 120 ns.
+        */
+       if (host->cclk < 25000000)
+               udelay(30);
+       else
+               ndelay(120);
+}
+
 /*
  * This must be called with host->lock held
  */
@@ -1264,6 +1285,7 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
        mmci_set_clkreg(host, ios->clock);
        mmci_write_pwrreg(host, pwr);
+       mmci_reg_delay(host);
 
        spin_unlock_irqrestore(&host->lock, flags);
 
@@ -1510,23 +1532,6 @@ static int mmci_probe(struct amba_device *dev,
                mmc->f_max = min(host->mclk, fmax);
        dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max);
 
-       host->pinctrl = devm_pinctrl_get(&dev->dev);
-       if (IS_ERR(host->pinctrl)) {
-               ret = PTR_ERR(host->pinctrl);
-               goto clk_disable;
-       }
-
-       host->pins_default = pinctrl_lookup_state(host->pinctrl,
-                       PINCTRL_STATE_DEFAULT);
-
-       /* enable pins to be muxed in and configured */
-       if (!IS_ERR(host->pins_default)) {
-               ret = pinctrl_select_state(host->pinctrl, host->pins_default);
-               if (ret)
-                       dev_warn(&dev->dev, "could not set default pins\n");
-       } else
-               dev_warn(&dev->dev, "could not get default pinstate\n");
-
        /* Get regulators and the supported OCR mask */
        mmc_regulator_get_supply(mmc);
        if (!mmc->ocr_avail)
@@ -1760,6 +1765,41 @@ static int mmci_resume(struct device *dev)
 #endif
 
 #ifdef CONFIG_PM_RUNTIME
+static void mmci_save(struct mmci_host *host)
+{
+       unsigned long flags;
+
+       if (host->variant->pwrreg_nopower) {
+               spin_lock_irqsave(&host->lock, flags);
+
+               writel(0, host->base + MMCIMASK0);
+               writel(0, host->base + MMCIDATACTRL);
+               writel(0, host->base + MMCIPOWER);
+               writel(0, host->base + MMCICLOCK);
+               mmci_reg_delay(host);
+
+               spin_unlock_irqrestore(&host->lock, flags);
+       }
+
+}
+
+static void mmci_restore(struct mmci_host *host)
+{
+       unsigned long flags;
+
+       if (host->variant->pwrreg_nopower) {
+               spin_lock_irqsave(&host->lock, flags);
+
+               writel(host->clk_reg, host->base + MMCICLOCK);
+               writel(host->datactrl_reg, host->base + MMCIDATACTRL);
+               writel(host->pwr_reg, host->base + MMCIPOWER);
+               writel(MCI_IRQENABLE, host->base + MMCIMASK0);
+               mmci_reg_delay(host);
+
+               spin_unlock_irqrestore(&host->lock, flags);
+       }
+}
+
 static int mmci_runtime_suspend(struct device *dev)
 {
        struct amba_device *adev = to_amba_device(dev);
@@ -1767,6 +1807,8 @@ static int mmci_runtime_suspend(struct device *dev)
 
        if (mmc) {
                struct mmci_host *host = mmc_priv(mmc);
+               pinctrl_pm_select_sleep_state(dev);
+               mmci_save(host);
                clk_disable_unprepare(host->clk);
        }
 
@@ -1781,6 +1823,8 @@ static int mmci_runtime_resume(struct device *dev)
        if (mmc) {
                struct mmci_host *host = mmc_priv(mmc);
                clk_prepare_enable(host->clk);
+               mmci_restore(host);
+               pinctrl_pm_select_default_state(dev);
        }
 
        return 0;
index 69080fab637520af2a9ea8b4a6ba49ae52b0344f..168bc72f7a94a9b662d7c0a97775c781d4d769aa 100644 (file)
@@ -200,10 +200,6 @@ struct mmci_host {
        struct sg_mapping_iter  sg_miter;
        unsigned int            size;
 
-       /* pinctrl handles */
-       struct pinctrl          *pinctrl;
-       struct pinctrl_state    *pins_default;
-
 #ifdef CONFIG_DMA_ENGINE
        /* DMA stuff */
        struct dma_chan         *dma_current;
index cdd4ce0d7c90c91526cb447996c2607603bb0195..ef19874fcd1f4dcd8ab6d9821091f542021ccc8f 100644 (file)
@@ -310,8 +310,9 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
                        dma_mask = DMA_BIT_MASK(32);
                }
 
-               dev->dma_mask = &dev->coherent_dma_mask;
-               dev->coherent_dma_mask = dma_mask;
+               err = dma_coerce_mask_and_coherent(dev, dma_mask);
+               if (err)
+                       goto err_free;
        }
 
        if (c->slot) {
index 87ed3fb5149ace85aef3338526741e5010ee1d9d..f344659dceac2739f47e032cbaaec2c54c86b6f6 100644 (file)
@@ -113,14 +113,14 @@ static const struct sh_mobile_sdhi_ops sdhi_ops = {
 };
 
 static const struct of_device_id sh_mobile_sdhi_of_match[] = {
-       { .compatible = "renesas,shmobile-sdhi" },
-       { .compatible = "renesas,sh7372-sdhi" },
-       { .compatible = "renesas,sh73a0-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
-       { .compatible = "renesas,r8a73a4-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
-       { .compatible = "renesas,r8a7740-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
-       { .compatible = "renesas,r8a7778-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
-       { .compatible = "renesas,r8a7779-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
-       { .compatible = "renesas,r8a7790-sdhi", .data = &sh_mobile_sdhi_of_cfg[0], },
+       { .compatible = "renesas,sdhi-shmobile" },
+       { .compatible = "renesas,sdhi-sh7372" },
+       { .compatible = "renesas,sdhi-sh73a0", .data = &sh_mobile_sdhi_of_cfg[0], },
+       { .compatible = "renesas,sdhi-r8a73a4", .data = &sh_mobile_sdhi_of_cfg[0], },
+       { .compatible = "renesas,sdhi-r8a7740", .data = &sh_mobile_sdhi_of_cfg[0], },
+       { .compatible = "renesas,sdhi-r8a7778", .data = &sh_mobile_sdhi_of_cfg[0], },
+       { .compatible = "renesas,sdhi-r8a7779", .data = &sh_mobile_sdhi_of_cfg[0], },
+       { .compatible = "renesas,sdhi-r8a7790", .data = &sh_mobile_sdhi_of_cfg[0], },
        {},
 };
 MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match);
index 5db900d917f92434f5941a393bcb9045ee99bd6c..dd03dfdfb0d65e0ded1b0a124221663b586482b5 100644 (file)
@@ -1236,7 +1236,6 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_OF
 static struct of_device_id pxa3xx_nand_dt_ids[] = {
        {
                .compatible = "marvell,pxa3xx-nand",
@@ -1284,12 +1283,6 @@ static int pxa3xx_nand_probe_dt(struct platform_device *pdev)
 
        return 0;
 }
-#else
-static inline int pxa3xx_nand_probe_dt(struct platform_device *pdev)
-{
-       return 0;
-}
-#endif
 
 static int pxa3xx_nand_probe(struct platform_device *pdev)
 {
index 91f179d5135c7542f7bbf4dfb36ea75e23dac4e7..f428ef57437279ec4bbf15e1c7e8e9b6a9da7a2c 100644 (file)
@@ -1472,7 +1472,7 @@ void bond_alb_monitor(struct work_struct *work)
        bond_info->lp_counter++;
 
        /* send learning packets */
-       if (bond_info->lp_counter >= BOND_ALB_LP_TICKS) {
+       if (bond_info->lp_counter >= BOND_ALB_LP_TICKS(bond)) {
                /* change of curr_active_slave involves swapping of mac addresses.
                 * in order to avoid this swapping from happening while
                 * sending the learning packets, the curr_slave_lock must be held for
index 28d8e4c7dc06d07e2aa396943adf6b391c7d7a61..c5eff5dafdfeab12ee4849fe75d9117d70c4859f 100644 (file)
@@ -36,14 +36,15 @@ struct slave;
                                         * Used for division - never set
                                         * to zero !!!
                                         */
-#define BOND_ALB_LP_INTERVAL       1   /* In seconds, periodic send of
-                                        * learning packets to the switch
-                                        */
+#define BOND_ALB_DEFAULT_LP_INTERVAL 1
+#define BOND_ALB_LP_INTERVAL(bond) (bond->params.lp_interval)  /* In seconds, periodic send of
+                                                                * learning packets to the switch
+                                                                */
 
 #define BOND_TLB_REBALANCE_TICKS (BOND_TLB_REBALANCE_INTERVAL \
                                  * ALB_TIMER_TICKS_PER_SEC)
 
-#define BOND_ALB_LP_TICKS (BOND_ALB_LP_INTERVAL \
+#define BOND_ALB_LP_TICKS(bond) (BOND_ALB_LP_INTERVAL(bond) \
                           * ALB_TIMER_TICKS_PER_SEC)
 
 #define TLB_HASH_TABLE_SIZE 256        /* The size of the clients hash table.
index 72df399c4ab33e89c4b5380a6c1c4ecce31c8a32..e883bfe2e727aa1bf6fd2fb2cea2375578c8c06d 100644 (file)
@@ -1724,6 +1724,7 @@ static int __bond_release_one(struct net_device *bond_dev,
        struct bonding *bond = netdev_priv(bond_dev);
        struct slave *slave, *oldcurrent;
        struct sockaddr addr;
+       int old_flags = bond_dev->flags;
        netdev_features_t old_features = bond_dev->features;
 
        /* slave is not a slave or master is not master of this slave */
@@ -1855,12 +1856,18 @@ static int __bond_release_one(struct net_device *bond_dev,
         * bond_change_active_slave(..., NULL)
         */
        if (!USES_PRIMARY(bond->params.mode)) {
-               /* unset promiscuity level from slave */
-               if (bond_dev->flags & IFF_PROMISC)
+               /* unset promiscuity level from slave
+                * NOTE: The NETDEV_CHANGEADDR call above may change the value
+                * of the IFF_PROMISC flag in the bond_dev, but we need the
+                * value of that flag before that change, as that was the value
+                * when this slave was attached, so we cache at the start of the
+                * function and use it here. Same goes for ALLMULTI below
+                */
+               if (old_flags & IFF_PROMISC)
                        dev_set_promiscuity(slave_dev, -1);
 
                /* unset allmulti level from slave */
-               if (bond_dev->flags & IFF_ALLMULTI)
+               if (old_flags & IFF_ALLMULTI)
                        dev_set_allmulti(slave_dev, -1);
 
                bond_hw_addr_flush(bond_dev, slave_dev);
@@ -4416,6 +4423,7 @@ static int bond_check_params(struct bond_params *params)
        params->all_slaves_active = all_slaves_active;
        params->resend_igmp = resend_igmp;
        params->min_links = min_links;
+       params->lp_interval = BOND_ALB_DEFAULT_LP_INTERVAL;
 
        if (primary) {
                strncpy(params->primary, primary, IFNAMSIZ);
index eeab40b01b7ac779aa05b81ad145774be9260221..c29b836749b6323fe86c35e7762b25a3c8596978 100644 (file)
@@ -1699,6 +1699,44 @@ out:
 static DEVICE_ATTR(resend_igmp, S_IRUGO | S_IWUSR,
                   bonding_show_resend_igmp, bonding_store_resend_igmp);
 
+
+static ssize_t bonding_show_lp_interval(struct device *d,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct bonding *bond = to_bond(d);
+       return sprintf(buf, "%d\n", bond->params.lp_interval);
+}
+
+static ssize_t bonding_store_lp_interval(struct device *d,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct bonding *bond = to_bond(d);
+       int new_value, ret = count;
+
+       if (sscanf(buf, "%d", &new_value) != 1) {
+               pr_err("%s: no lp interval value specified.\n",
+                       bond->dev->name);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (new_value <= 0) {
+               pr_err ("%s: lp_interval must be between 1 and %d\n",
+                       bond->dev->name, INT_MAX);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       bond->params.lp_interval = new_value;
+out:
+       return ret;
+}
+
+static DEVICE_ATTR(lp_interval, S_IRUGO | S_IWUSR,
+                  bonding_show_lp_interval, bonding_store_lp_interval);
+
 static struct attribute *per_bond_attrs[] = {
        &dev_attr_slaves.attr,
        &dev_attr_mode.attr,
@@ -1729,6 +1767,7 @@ static struct attribute *per_bond_attrs[] = {
        &dev_attr_all_slaves_active.attr,
        &dev_attr_resend_igmp.attr,
        &dev_attr_min_links.attr,
+       &dev_attr_lp_interval.attr,
        NULL,
 };
 
index 7ad8bd5cc9472b8caa75c6b9bcd1786270b2e1de..03cf3fd14490c4e4dcf8cd2d61f8bca99c9d55db 100644 (file)
@@ -176,6 +176,7 @@ struct bond_params {
        int tx_queues;
        int all_slaves_active;
        int resend_igmp;
+       int lp_interval;
 };
 
 struct bond_parm_tbl {
index 71c677e651d7cbead0f673f53a93e89514e74eb3..3f21142138b79868a0f18fa7d246432e99d96192 100644 (file)
@@ -702,7 +702,6 @@ static int flexcan_chip_start(struct net_device *dev)
 {
        struct flexcan_priv *priv = netdev_priv(dev);
        struct flexcan_regs __iomem *regs = priv->base;
-       unsigned int i;
        int err;
        u32 reg_mcr, reg_ctrl;
 
@@ -772,17 +771,6 @@ static int flexcan_chip_start(struct net_device *dev)
        netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl);
        flexcan_write(reg_ctrl, &regs->ctrl);
 
-       for (i = 0; i < ARRAY_SIZE(regs->cantxfg); i++) {
-               flexcan_write(0, &regs->cantxfg[i].can_ctrl);
-               flexcan_write(0, &regs->cantxfg[i].can_id);
-               flexcan_write(0, &regs->cantxfg[i].data[0]);
-               flexcan_write(0, &regs->cantxfg[i].data[1]);
-
-               /* put MB into rx queue */
-               flexcan_write(FLEXCAN_MB_CNT_CODE(0x4),
-                       &regs->cantxfg[i].can_ctrl);
-       }
-
        /* acceptance mask/acceptance code (accept everything) */
        flexcan_write(0x0, &regs->rxgmask);
        flexcan_write(0x0, &regs->rx14mask);
index 874188ba06f7172fed36b93db05be06ae0e2bd59..25377e547f9b01f49167caa13f510c51fb2bd1c7 100644 (file)
@@ -76,6 +76,10 @@ MODULE_PARM_DESC(maxdev, "Maximum number of slcan interfaces");
 /* maximum rx buffer len: extended CAN frame with timestamp */
 #define SLC_MTU (sizeof("T1111222281122334455667788EA5F\r")+1)
 
+#define SLC_CMD_LEN 1
+#define SLC_SFF_ID_LEN 3
+#define SLC_EFF_ID_LEN 8
+
 struct slcan {
        int                     magic;
 
@@ -142,47 +146,63 @@ static void slc_bump(struct slcan *sl)
 {
        struct sk_buff *skb;
        struct can_frame cf;
-       int i, dlc_pos, tmp;
-       unsigned long ultmp;
-       char cmd = sl->rbuff[0];
-
-       if ((cmd != 't') && (cmd != 'T') && (cmd != 'r') && (cmd != 'R'))
+       int i, tmp;
+       u32 tmpid;
+       char *cmd = sl->rbuff;
+
+       cf.can_id = 0;
+
+       switch (*cmd) {
+       case 'r':
+               cf.can_id = CAN_RTR_FLAG;
+               /* fallthrough */
+       case 't':
+               /* store dlc ASCII value and terminate SFF CAN ID string */
+               cf.can_dlc = sl->rbuff[SLC_CMD_LEN + SLC_SFF_ID_LEN];
+               sl->rbuff[SLC_CMD_LEN + SLC_SFF_ID_LEN] = 0;
+               /* point to payload data behind the dlc */
+               cmd += SLC_CMD_LEN + SLC_SFF_ID_LEN + 1;
+               break;
+       case 'R':
+               cf.can_id = CAN_RTR_FLAG;
+               /* fallthrough */
+       case 'T':
+               cf.can_id |= CAN_EFF_FLAG;
+               /* store dlc ASCII value and terminate EFF CAN ID string */
+               cf.can_dlc = sl->rbuff[SLC_CMD_LEN + SLC_EFF_ID_LEN];
+               sl->rbuff[SLC_CMD_LEN + SLC_EFF_ID_LEN] = 0;
+               /* point to payload data behind the dlc */
+               cmd += SLC_CMD_LEN + SLC_EFF_ID_LEN + 1;
+               break;
+       default:
                return;
+       }
 
-       if (cmd & 0x20) /* tiny chars 'r' 't' => standard frame format */
-               dlc_pos = 4; /* dlc position tiiid */
-       else
-               dlc_pos = 9; /* dlc position Tiiiiiiiid */
-
-       if (!((sl->rbuff[dlc_pos] >= '0') && (sl->rbuff[dlc_pos] < '9')))
+       if (kstrtou32(sl->rbuff + SLC_CMD_LEN, 16, &tmpid))
                return;
 
-       cf.can_dlc = sl->rbuff[dlc_pos] - '0'; /* get can_dlc from ASCII val */
+       cf.can_id |= tmpid;
 
-       sl->rbuff[dlc_pos] = 0; /* terminate can_id string */
-
-       if (kstrtoul(sl->rbuff+1, 16, &ultmp))
+       /* get can_dlc from sanitized ASCII value */
+       if (cf.can_dlc >= '0' && cf.can_dlc < '9')
+               cf.can_dlc -= '0';
+       else
                return;
 
-       cf.can_id = ultmp;
-
-       if (!(cmd & 0x20)) /* NO tiny chars => extended frame format */
-               cf.can_id |= CAN_EFF_FLAG;
-
-       if ((cmd | 0x20) == 'r') /* RTR frame */
-               cf.can_id |= CAN_RTR_FLAG;
-
        *(u64 *) (&cf.data) = 0; /* clear payload */
 
-       for (i = 0, dlc_pos++; i < cf.can_dlc; i++) {
-               tmp = hex_to_bin(sl->rbuff[dlc_pos++]);
-               if (tmp < 0)
-                       return;
-               cf.data[i] = (tmp << 4);
-               tmp = hex_to_bin(sl->rbuff[dlc_pos++]);
-               if (tmp < 0)
-                       return;
-               cf.data[i] |= tmp;
+       /* RTR frames may have a dlc > 0 but they never have any data bytes */
+       if (!(cf.can_id & CAN_RTR_FLAG)) {
+               for (i = 0; i < cf.can_dlc; i++) {
+                       tmp = hex_to_bin(*cmd++);
+                       if (tmp < 0)
+                               return;
+                       cf.data[i] = (tmp << 4);
+                       tmp = hex_to_bin(*cmd++);
+                       if (tmp < 0)
+                               return;
+                       cf.data[i] |= tmp;
+               }
        }
 
        skb = dev_alloc_skb(sizeof(struct can_frame) +
@@ -209,7 +229,6 @@ static void slc_bump(struct slcan *sl)
 /* parse tty input stream */
 static void slcan_unesc(struct slcan *sl, unsigned char s)
 {
-
        if ((s == '\r') || (s == '\a')) { /* CR or BEL ends the pdu */
                if (!test_and_clear_bit(SLF_ERROR, &sl->flags) &&
                    (sl->rcount > 4))  {
@@ -236,27 +255,46 @@ static void slcan_unesc(struct slcan *sl, unsigned char s)
 /* Encapsulate one can_frame and stuff into a TTY queue. */
 static void slc_encaps(struct slcan *sl, struct can_frame *cf)
 {
-       int actual, idx, i;
-       char cmd;
+       int actual, i;
+       unsigned char *pos;
+       unsigned char *endpos;
+       canid_t id = cf->can_id;
+
+       pos = sl->xbuff;
 
        if (cf->can_id & CAN_RTR_FLAG)
-               cmd = 'R'; /* becomes 'r' in standard frame format */
+               *pos = 'R'; /* becomes 'r' in standard frame format (SFF) */
        else
-               cmd = 'T'; /* becomes 't' in standard frame format */
+               *pos = 'T'; /* becomes 't' in standard frame format (SSF) */
 
-       if (cf->can_id & CAN_EFF_FLAG)
-               sprintf(sl->xbuff, "%c%08X%d", cmd,
-                       cf->can_id & CAN_EFF_MASK, cf->can_dlc);
-       else
-               sprintf(sl->xbuff, "%c%03X%d", cmd | 0x20,
-                       cf->can_id & CAN_SFF_MASK, cf->can_dlc);
+       /* determine number of chars for the CAN-identifier */
+       if (cf->can_id & CAN_EFF_FLAG) {
+               id &= CAN_EFF_MASK;
+               endpos = pos + SLC_EFF_ID_LEN;
+       } else {
+               *pos |= 0x20; /* convert R/T to lower case for SFF */
+               id &= CAN_SFF_MASK;
+               endpos = pos + SLC_SFF_ID_LEN;
+       }
 
-       idx = strlen(sl->xbuff);
+       /* build 3 (SFF) or 8 (EFF) digit CAN identifier */
+       pos++;
+       while (endpos >= pos) {
+               *endpos-- = hex_asc_upper[id & 0xf];
+               id >>= 4;
+       }
+
+       pos += (cf->can_id & CAN_EFF_FLAG) ? SLC_EFF_ID_LEN : SLC_SFF_ID_LEN;
 
-       for (i = 0; i < cf->can_dlc; i++)
-               sprintf(&sl->xbuff[idx + 2*i], "%02X", cf->data[i]);
+       *pos++ = cf->can_dlc + '0';
+
+       /* RTR frames may have a dlc > 0 but they never have any data bytes */
+       if (!(cf->can_id & CAN_RTR_FLAG)) {
+               for (i = 0; i < cf->can_dlc; i++)
+                       pos = hex_byte_pack_upper(pos, cf->data[i]);
+       }
 
-       strcat(sl->xbuff, "\r"); /* add terminating character */
+       *pos++ = '\r';
 
        /* Order of next two lines is *very* important.
         * When we are sending a little amount of data,
@@ -267,8 +305,8 @@ static void slc_encaps(struct slcan *sl, struct can_frame *cf)
         *       14 Oct 1994  Dmitry Gorodchanin.
         */
        set_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
-       actual = sl->tty->ops->write(sl->tty, sl->xbuff, strlen(sl->xbuff));
-       sl->xleft = strlen(sl->xbuff) - actual;
+       actual = sl->tty->ops->write(sl->tty, sl->xbuff, pos - sl->xbuff);
+       sl->xleft = (pos - sl->xbuff) - actual;
        sl->xhead = sl->xbuff + actual;
        sl->dev->stats.tx_bytes += cf->can_dlc;
 }
@@ -286,11 +324,13 @@ static void slcan_write_wakeup(struct tty_struct *tty)
        if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev))
                return;
 
+       spin_lock(&sl->lock);
        if (sl->xleft <= 0)  {
                /* Now serial buffer is almost free & we can start
                 * transmission of another packet */
                sl->dev->stats.tx_packets++;
                clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+               spin_unlock(&sl->lock);
                netif_wake_queue(sl->dev);
                return;
        }
@@ -298,6 +338,7 @@ static void slcan_write_wakeup(struct tty_struct *tty)
        actual = tty->ops->write(tty, sl->xhead, sl->xleft);
        sl->xleft -= actual;
        sl->xhead += actual;
+       spin_unlock(&sl->lock);
 }
 
 /* Send a can_frame to a TTY queue. */
index a0f647f92bf55c7388034f9fbd0a377cc1225901..0b7a4c3b01a2976176878607bd457a9ea282e21e 100644 (file)
@@ -463,7 +463,7 @@ static int peak_usb_start(struct peak_usb_device *dev)
        if (i < PCAN_USB_MAX_TX_URBS) {
                if (i == 0) {
                        netdev_err(netdev, "couldn't setup any tx URB\n");
-                       return err;
+                       goto err_tx;
                }
 
                netdev_warn(netdev, "tx performance may be slow\n");
@@ -472,7 +472,7 @@ static int peak_usb_start(struct peak_usb_device *dev)
        if (dev->adapter->dev_start) {
                err = dev->adapter->dev_start(dev);
                if (err)
-                       goto failed;
+                       goto err_adapter;
        }
 
        dev->state |= PCAN_USB_STATE_STARTED;
@@ -481,19 +481,26 @@ static int peak_usb_start(struct peak_usb_device *dev)
        if (dev->adapter->dev_set_bus) {
                err = dev->adapter->dev_set_bus(dev, 1);
                if (err)
-                       goto failed;
+                       goto err_adapter;
        }
 
        dev->can.state = CAN_STATE_ERROR_ACTIVE;
 
        return 0;
 
-failed:
+err_adapter:
        if (err == -ENODEV)
                netif_device_detach(dev->netdev);
 
        netdev_warn(netdev, "couldn't submit control: %d\n", err);
 
+       for (i = 0; i < PCAN_USB_MAX_TX_URBS; i++) {
+               usb_free_urb(dev->tx_contexts[i].urb);
+               dev->tx_contexts[i].urb = NULL;
+       }
+err_tx:
+       usb_kill_anchored_urbs(&dev->rx_submitted);
+
        return err;
 }
 
index e66684a438f52cf3f4fdde9e1effcec0577ceb8f..75fb1d20d6fd8ebff82f34da2b99271c1894fb4a 100644 (file)
@@ -530,7 +530,7 @@ static int bfin_mac_ethtool_setwol(struct net_device *dev,
        if (lp->wol && !lp->irq_wake_requested) {
                /* register wake irq handler */
                rc = request_irq(IRQ_MAC_WAKEDET, bfin_mac_wake_interrupt,
-                                IRQF_DISABLED, "EMAC_WAKE", dev);
+                                0, "EMAC_WAKE", dev);
                if (rc)
                        return rc;
                lp->irq_wake_requested = true;
@@ -1686,7 +1686,7 @@ static int bfin_mac_probe(struct platform_device *pdev)
        /* now, enable interrupts */
        /* register irq handler */
        rc = request_irq(IRQ_MAC_RX, bfin_mac_interrupt,
-                       IRQF_DISABLED, "EMAC_RX", ndev);
+                       0, "EMAC_RX", ndev);
        if (rc) {
                dev_err(&pdev->dev, "Cannot request Blackfin MAC RX IRQ!\n");
                rc = -EBUSY;
index d6b20296b8e46a7273f0f15296129fbe75d0e02a..3d8c6b2cdea4ca5906e0abb09a0523a5aa03b74c 100644 (file)
@@ -358,7 +358,7 @@ static int __init lance_probe( struct net_device *dev)
 
        REGA(CSR0) = CSR0_STOP;
 
-       if (request_irq(LANCE_IRQ, lance_interrupt, IRQF_DISABLED, "SUN3 Lance", dev) < 0) {
+       if (request_irq(LANCE_IRQ, lance_interrupt, 0, "SUN3 Lance", dev) < 0) {
 #ifdef CONFIG_SUN3
                iounmap((void __iomem *)ioaddr);
 #endif
index 027398ebbba6aae4bfe946bd6d74bc002f671cab..fc95b235e210d058545efd889537c2a8dea08a45 100644 (file)
@@ -1188,7 +1188,7 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct alx_priv *alx;
        struct alx_hw *hw;
        bool phy_configured;
-       int bars, pm_cap, err;
+       int bars, err;
 
        err = pci_enable_device_mem(pdev);
        if (err)
@@ -1225,18 +1225,13 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        pci_enable_pcie_error_reporting(pdev);
        pci_set_master(pdev);
 
-       pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
-       if (pm_cap == 0) {
+       if (!pdev->pm_cap) {
                dev_err(&pdev->dev,
                        "Can't find power management capability, aborting\n");
                err = -EIO;
                goto out_pci_release;
        }
 
-       err = pci_set_power_state(pdev, PCI_D0);
-       if (err)
-               goto out_pci_release;
-
        netdev = alloc_etherdev(sizeof(*alx));
        if (!netdev) {
                err = -ENOMEM;
index 9b017d9c58e94e5ab671aeda2cfcc969cc561c6e..b4d20182549b6caa43892c26917bc80d84b35705 100644 (file)
@@ -2183,8 +2183,7 @@ static int b44_init_one(struct ssb_device *sdev,
                goto err_out_free_dev;
        }
 
-       if (dma_set_mask(sdev->dma_dev, DMA_BIT_MASK(30)) ||
-           dma_set_coherent_mask(sdev->dma_dev, DMA_BIT_MASK(30))) {
+       if (dma_set_mask_and_coherent(sdev->dma_dev, DMA_BIT_MASK(30))) {
                dev_err(sdev->dev,
                        "Required 30BIT DMA mask unsupported by the system\n");
                goto err_out_powerdown;
index eec0af45b85996b2cdb02a2509563e944f93a742..249468f953651480a5e0b897d582dd09743c6c3b 100644 (file)
@@ -157,6 +157,7 @@ static netdev_tx_t bgmac_dma_tx_add(struct bgmac *bgmac,
        if (++ring->end >= BGMAC_TX_RING_SLOTS)
                ring->end = 0;
        bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_INDEX,
+                   ring->index_base +
                    ring->end * sizeof(struct bgmac_dma_desc));
 
        /* Always keep one slot free to allow detecting bugged calls. */
@@ -181,6 +182,8 @@ static void bgmac_dma_tx_free(struct bgmac *bgmac, struct bgmac_dma_ring *ring)
        /* The last slot that hardware didn't consume yet */
        empty_slot = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_STATUS);
        empty_slot &= BGMAC_DMA_TX_STATDPTR;
+       empty_slot -= ring->index_base;
+       empty_slot &= BGMAC_DMA_TX_STATDPTR;
        empty_slot /= sizeof(struct bgmac_dma_desc);
 
        while (ring->start != empty_slot) {
@@ -274,6 +277,8 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring,
 
        end_slot = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_STATUS);
        end_slot &= BGMAC_DMA_RX_STATDPTR;
+       end_slot -= ring->index_base;
+       end_slot &= BGMAC_DMA_RX_STATDPTR;
        end_slot /= sizeof(struct bgmac_dma_desc);
 
        ring->end = end_slot;
@@ -418,9 +423,6 @@ static int bgmac_dma_alloc(struct bgmac *bgmac)
                ring = &bgmac->tx_ring[i];
                ring->num_slots = BGMAC_TX_RING_SLOTS;
                ring->mmio_base = ring_base[i];
-               if (bgmac_dma_unaligned(bgmac, ring, BGMAC_DMA_RING_TX))
-                       bgmac_warn(bgmac, "TX on ring 0x%X supports unaligned addressing but this feature is not implemented\n",
-                                  ring->mmio_base);
 
                /* Alloc ring of descriptors */
                size = ring->num_slots * sizeof(struct bgmac_dma_desc);
@@ -435,6 +437,13 @@ static int bgmac_dma_alloc(struct bgmac *bgmac)
                if (ring->dma_base & 0xC0000000)
                        bgmac_warn(bgmac, "DMA address using 0xC0000000 bit(s), it may need translation trick\n");
 
+               ring->unaligned = bgmac_dma_unaligned(bgmac, ring,
+                                                     BGMAC_DMA_RING_TX);
+               if (ring->unaligned)
+                       ring->index_base = lower_32_bits(ring->dma_base);
+               else
+                       ring->index_base = 0;
+
                /* No need to alloc TX slots yet */
        }
 
@@ -444,9 +453,6 @@ static int bgmac_dma_alloc(struct bgmac *bgmac)
                ring = &bgmac->rx_ring[i];
                ring->num_slots = BGMAC_RX_RING_SLOTS;
                ring->mmio_base = ring_base[i];
-               if (bgmac_dma_unaligned(bgmac, ring, BGMAC_DMA_RING_RX))
-                       bgmac_warn(bgmac, "RX on ring 0x%X supports unaligned addressing but this feature is not implemented\n",
-                                  ring->mmio_base);
 
                /* Alloc ring of descriptors */
                size = ring->num_slots * sizeof(struct bgmac_dma_desc);
@@ -462,6 +468,13 @@ static int bgmac_dma_alloc(struct bgmac *bgmac)
                if (ring->dma_base & 0xC0000000)
                        bgmac_warn(bgmac, "DMA address using 0xC0000000 bit(s), it may need translation trick\n");
 
+               ring->unaligned = bgmac_dma_unaligned(bgmac, ring,
+                                                     BGMAC_DMA_RING_RX);
+               if (ring->unaligned)
+                       ring->index_base = lower_32_bits(ring->dma_base);
+               else
+                       ring->index_base = 0;
+
                /* Alloc RX slots */
                for (j = 0; j < ring->num_slots; j++) {
                        err = bgmac_dma_rx_skb_for_slot(bgmac, &ring->slots[j]);
@@ -489,12 +502,14 @@ static void bgmac_dma_init(struct bgmac *bgmac)
        for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) {
                ring = &bgmac->tx_ring[i];
 
-               /* We don't implement unaligned addressing, so enable first */
-               bgmac_dma_tx_enable(bgmac, ring);
+               if (!ring->unaligned)
+                       bgmac_dma_tx_enable(bgmac, ring);
                bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_RINGLO,
                            lower_32_bits(ring->dma_base));
                bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_RINGHI,
                            upper_32_bits(ring->dma_base));
+               if (ring->unaligned)
+                       bgmac_dma_tx_enable(bgmac, ring);
 
                ring->start = 0;
                ring->end = 0;  /* Points the slot that should *not* be read */
@@ -505,12 +520,14 @@ static void bgmac_dma_init(struct bgmac *bgmac)
 
                ring = &bgmac->rx_ring[i];
 
-               /* We don't implement unaligned addressing, so enable first */
-               bgmac_dma_rx_enable(bgmac, ring);
+               if (!ring->unaligned)
+                       bgmac_dma_rx_enable(bgmac, ring);
                bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGLO,
                            lower_32_bits(ring->dma_base));
                bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGHI,
                            upper_32_bits(ring->dma_base));
+               if (ring->unaligned)
+                       bgmac_dma_rx_enable(bgmac, ring);
 
                for (j = 0, dma_desc = ring->cpu_base; j < ring->num_slots;
                     j++, dma_desc++) {
@@ -531,6 +548,7 @@ static void bgmac_dma_init(struct bgmac *bgmac)
                }
 
                bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX,
+                           ring->index_base +
                            ring->num_slots * sizeof(struct bgmac_dma_desc));
 
                ring->start = 0;
@@ -908,10 +926,10 @@ static void bgmac_chip_reset(struct bgmac *bgmac)
                struct bcma_drv_cc *cc = &bgmac->core->bus->drv_cc;
                u8 et_swtype = 0;
                u8 sw_type = BGMAC_CHIPCTL_1_SW_TYPE_EPHY |
-                            BGMAC_CHIPCTL_1_IF_TYPE_RMII;
-               char buf[2];
+                            BGMAC_CHIPCTL_1_IF_TYPE_MII;
+               char buf[4];
 
-               if (bcm47xx_nvram_getenv("et_swtype", buf, 1) > 0) {
+               if (bcm47xx_nvram_getenv("et_swtype", buf, sizeof(buf)) > 0) {
                        if (kstrtou8(buf, 0, &et_swtype))
                                bgmac_err(bgmac, "Failed to parse et_swtype (%s)\n",
                                          buf);
index 98d4b5fcc070b4c0d10fbf09d9510dd6570492d3..66c8afbdc8c7fd863337da4795df8df9443ae120 100644 (file)
 
 #define BGMAC_CHIPCTL_1_IF_TYPE_MASK           0x00000030
 #define BGMAC_CHIPCTL_1_IF_TYPE_RMII           0x00000000
-#define BGMAC_CHIPCTL_1_IF_TYPE_MI             0x00000010
+#define BGMAC_CHIPCTL_1_IF_TYPE_MII            0x00000010
 #define BGMAC_CHIPCTL_1_IF_TYPE_RGMII          0x00000020
 #define BGMAC_CHIPCTL_1_SW_TYPE_MASK           0x000000C0
 #define BGMAC_CHIPCTL_1_SW_TYPE_EPHY           0x00000000
@@ -384,6 +384,8 @@ struct bgmac_dma_ring {
        u16 mmio_base;
        struct bgmac_dma_desc *cpu_base;
        dma_addr_t dma_base;
+       u32 index_base; /* Used for unaligned rings only, otherwise 0 */
+       bool unaligned;
 
        struct bgmac_slot_info slots[BGMAC_RX_RING_SLOTS];
 };
index 0c338026ce01e4473c2f28fc4f288fc122185670..97b3d32a98bd010ab1a1327ef7382e5bd64139b8 100644 (file)
@@ -246,8 +246,37 @@ enum {
        BNX2X_MAX_CNIC_ETH_CL_ID_IDX,
 };
 
-#define BNX2X_CNIC_START_ETH_CID(bp)   (BNX2X_NUM_NON_CNIC_QUEUES(bp) *\
+/* use a value high enough to be above all the PFs, which has least significant
+ * nibble as 8, so when cnic needs to come up with a CID for UIO to use to
+ * calculate doorbell address according to old doorbell configuration scheme
+ * (db_msg_sz 1 << 7 * cid + 0x40 DPM offset) it can come up with a valid number
+ * We must avoid coming up with cid 8 for iscsi since according to this method
+ * the designated UIO cid will come out 0 and it has a special handling for that
+ * case which doesn't suit us. Therefore will will cieling to closes cid which
+ * has least signigifcant nibble 8 and if it is 8 we will move forward to 0x18.
+ */
+
+#define BNX2X_1st_NON_L2_ETH_CID(bp)   (BNX2X_NUM_NON_CNIC_QUEUES(bp) * \
                                         (bp)->max_cos)
+/* amount of cids traversed by UIO's DPM addition to doorbell */
+#define UIO_DPM                                8
+/* roundup to DPM offset */
+#define UIO_ROUNDUP(bp)                        (roundup(BNX2X_1st_NON_L2_ETH_CID(bp), \
+                                        UIO_DPM))
+/* offset to nearest value which has lsb nibble matching DPM */
+#define UIO_CID_OFFSET(bp)             ((UIO_ROUNDUP(bp) + UIO_DPM) % \
+                                        (UIO_DPM * 2))
+/* add offset to rounded-up cid to get a value which could be used with UIO */
+#define UIO_DPM_ALIGN(bp)              (UIO_ROUNDUP(bp) + UIO_CID_OFFSET(bp))
+/* but wait - avoid UIO special case for cid 0 */
+#define UIO_DPM_CID0_OFFSET(bp)                ((UIO_DPM * 2) * \
+                                        (UIO_DPM_ALIGN(bp) == UIO_DPM))
+/* Properly DPM aligned CID dajusted to cid 0 secal case */
+#define BNX2X_CNIC_START_ETH_CID(bp)   (UIO_DPM_ALIGN(bp) + \
+                                        (UIO_DPM_CID0_OFFSET(bp)))
+/* how many cids were wasted  - need this value for cid allocation */
+#define UIO_CID_PAD(bp)                        (BNX2X_CNIC_START_ETH_CID(bp) - \
+                                        BNX2X_1st_NON_L2_ETH_CID(bp))
        /* iSCSI L2 */
 #define        BNX2X_ISCSI_ETH_CID(bp)         (BNX2X_CNIC_START_ETH_CID(bp))
        /* FCoE L2 */
@@ -1542,7 +1571,6 @@ struct bnx2x {
         */
        bool                    fcoe_init;
 
-       int                     pm_cap;
        int                     mrrs;
 
        struct delayed_work     sp_task;
@@ -1681,10 +1709,11 @@ struct bnx2x {
  * Maximum CID count that might be required by the bnx2x:
  * Max RSS * Max_Tx_Multi_Cos + FCoE + iSCSI
  */
+
 #define BNX2X_L2_CID_COUNT(bp) (BNX2X_NUM_ETH_QUEUES(bp) * BNX2X_MULTI_TX_COS \
-                               + 2 * CNIC_SUPPORT(bp))
+                               + CNIC_SUPPORT(bp) * (2 + UIO_CID_PAD(bp)))
 #define BNX2X_L2_MAX_CID(bp)   (BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS \
-                               + 2 * CNIC_SUPPORT(bp))
+                               + CNIC_SUPPORT(bp) * (2 + UIO_CID_PAD(bp)))
 #define L2_ILT_LINES(bp)       (DIV_ROUND_UP(BNX2X_L2_CID_COUNT(bp),\
                                        ILT_PAGE_CIDS))
 
index 90045c920d09c811bf5b8ce223574cecd3ce568f..e66beff2704d19241695fe5028e33efb3ca95519 100644 (file)
@@ -2481,8 +2481,7 @@ load_error_cnic2:
 load_error_cnic1:
        bnx2x_napi_disable_cnic(bp);
        /* Update the number of queues without the cnic queues */
-       rc = bnx2x_set_real_num_queues(bp, 0);
-       if (rc)
+       if (bnx2x_set_real_num_queues(bp, 0))
                BNX2X_ERR("Unable to set real_num_queues not including cnic\n");
 load_error_cnic0:
        BNX2X_ERR("CNIC-related load failed\n");
@@ -3008,16 +3007,16 @@ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state)
        u16 pmcsr;
 
        /* If there is no power capability, silently succeed */
-       if (!bp->pm_cap) {
+       if (!bp->pdev->pm_cap) {
                BNX2X_DEV_INFO("No power capability. Breaking.\n");
                return 0;
        }
 
-       pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr);
+       pci_read_config_word(bp->pdev, bp->pdev->pm_cap + PCI_PM_CTRL, &pmcsr);
 
        switch (state) {
        case PCI_D0:
-               pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
+               pci_write_config_word(bp->pdev, bp->pdev->pm_cap + PCI_PM_CTRL,
                                      ((pmcsr & ~PCI_PM_CTRL_STATE_MASK) |
                                       PCI_PM_CTRL_PME_STATUS));
 
@@ -3041,7 +3040,7 @@ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state)
                if (bp->wol)
                        pmcsr |= PCI_PM_CTRL_PME_ENABLE;
 
-               pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
+               pci_write_config_word(bp->pdev, bp->pdev->pm_cap + PCI_PM_CTRL,
                                      pmcsr);
 
                /* No more memory access after this point until
index 2612e3c715d4c0f198d458a69dcfba5d686c3300..324de5f05332e78aa6c108d23891105880ee5bd8 100644 (file)
@@ -1387,9 +1387,9 @@ static bool bnx2x_is_nvm_accessible(struct bnx2x *bp)
        u16 pm = 0;
        struct net_device *dev = pci_get_drvdata(bp->pdev);
 
-       if (bp->pm_cap)
+       if (bp->pdev->pm_cap)
                rc = pci_read_config_word(bp->pdev,
-                                         bp->pm_cap + PCI_PM_CTRL, &pm);
+                                         bp->pdev->pm_cap + PCI_PM_CTRL, &pm);
 
        if ((rc && !netif_running(dev)) ||
            (!rc && ((pm & PCI_PM_CTRL_STATE_MASK) != (__force u16)PCI_D0)))
index d60a2ea3da192a203a18cda07251c3e2ee60ab42..51468227bf3b75fc17d2abafb8b3bd9294d8494c 100644 (file)
@@ -175,6 +175,7 @@ typedef int (*read_sfp_module_eeprom_func_p)(struct bnx2x_phy *phy,
 #define EDC_MODE_LINEAR                                0x0022
 #define EDC_MODE_LIMITING                              0x0044
 #define EDC_MODE_PASSIVE_DAC                   0x0055
+#define EDC_MODE_ACTIVE_DAC                    0x0066
 
 /* ETS defines*/
 #define DCBX_INVALID_COS                                       (0xFF)
@@ -3684,6 +3685,41 @@ static void bnx2x_warpcore_enable_AN_KR2(struct bnx2x_phy *phy,
        bnx2x_update_link_attr(params, vars->link_attr_sync);
 }
 
+static void bnx2x_disable_kr2(struct link_params *params,
+                             struct link_vars *vars,
+                             struct bnx2x_phy *phy)
+{
+       struct bnx2x *bp = params->bp;
+       int i;
+       static struct bnx2x_reg_set reg_set[] = {
+               /* Step 1 - Program the TX/RX alignment markers */
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0x7690},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xe647},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0xc4f0},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0x7690},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xe647},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0xc4f0},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000c},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6000},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0000},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0002},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x0000},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x0af7},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x0af7},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0002},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0000}
+       };
+       DP(NETIF_MSG_LINK, "Disabling 20G-KR2\n");
+
+       for (i = 0; i < ARRAY_SIZE(reg_set); i++)
+               bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
+                                reg_set[i].val);
+       vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
+       bnx2x_update_link_attr(params, vars->link_attr_sync);
+
+       vars->check_kr2_recovery_cnt = CHECK_KR2_RECOVERY_CNT;
+}
+
 static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,
                                               struct link_params *params)
 {
@@ -3715,7 +3751,6 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
                                        struct link_params *params,
                                        struct link_vars *vars) {
        u16 lane, i, cl72_ctrl, an_adv = 0;
-       u16 ucode_ver;
        struct bnx2x *bp = params->bp;
        static struct bnx2x_reg_set reg_set[] = {
                {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
@@ -3806,15 +3841,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 
        /* Advertise pause */
        bnx2x_ext_phy_set_pause(params, phy, vars);
-       /* Set KR Autoneg Work-Around flag for Warpcore version older than D108
-        */
-       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                       MDIO_WC_REG_UC_INFO_B1_VERSION, &ucode_ver);
-       if (ucode_ver < 0xd108) {
-               DP(NETIF_MSG_LINK, "Enable AN KR work-around. WC ver:0x%x\n",
-                              ucode_ver);
-               vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
-       }
+       vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
        bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
                                 MDIO_WC_REG_DIGITAL5_MISC7, 0x100);
 
@@ -3838,6 +3865,8 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
                bnx2x_set_aer_mmd(params, phy);
 
                bnx2x_warpcore_enable_AN_KR2(phy, params, vars);
+       } else {
+               bnx2x_disable_kr2(params, vars, phy);
        }
 
        /* Enable Autoneg: only on the main lane */
@@ -4347,20 +4376,14 @@ static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy,
        struct bnx2x *bp = params->bp;
        u32 serdes_net_if;
        u16 gp_status1 = 0, lnkup = 0, lnkup_kr = 0;
-       u16 lane = bnx2x_get_warpcore_lane(phy, params);
 
        vars->turn_to_run_wc_rt = vars->turn_to_run_wc_rt ? 0 : 1;
 
        if (!vars->turn_to_run_wc_rt)
                return;
 
-       /* Return if there is no link partner */
-       if (!(bnx2x_warpcore_get_sigdet(phy, params))) {
-               DP(NETIF_MSG_LINK, "bnx2x_warpcore_get_sigdet false\n");
-               return;
-       }
-
        if (vars->rx_tx_asic_rst) {
+               u16 lane = bnx2x_get_warpcore_lane(phy, params);
                serdes_net_if = (REG_RD(bp, params->shmem_base +
                                offsetof(struct shmem_region, dev_info.
                                port_hw_config[params->port].default_cfg)) &
@@ -4375,14 +4398,8 @@ static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy,
                                /*10G KR*/
                        lnkup_kr = (gp_status1 >> (12+lane)) & 0x1;
 
-                       DP(NETIF_MSG_LINK,
-                               "gp_status1 0x%x\n", gp_status1);
-
                        if (lnkup_kr || lnkup) {
-                                       vars->rx_tx_asic_rst = 0;
-                                       DP(NETIF_MSG_LINK,
-                                       "link up, rx_tx_asic_rst 0x%x\n",
-                                       vars->rx_tx_asic_rst);
+                               vars->rx_tx_asic_rst = 0;
                        } else {
                                /* Reset the lane to see if link comes up.*/
                                bnx2x_warpcore_reset_lane(bp, phy, 1);
@@ -4507,10 +4524,14 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
                         * enabled transmitter to avoid current leakage in case
                         * no module is connected
                         */
-                       if (bnx2x_is_sfp_module_plugged(phy, params))
-                               bnx2x_sfp_module_detection(phy, params);
-                       else
-                               bnx2x_sfp_e3_set_transmitter(params, phy, 1);
+                       if ((params->loopback_mode == LOOPBACK_NONE) ||
+                           (params->loopback_mode == LOOPBACK_EXT)) {
+                               if (bnx2x_is_sfp_module_plugged(phy, params))
+                                       bnx2x_sfp_module_detection(phy, params);
+                               else
+                                       bnx2x_sfp_e3_set_transmitter(params,
+                                                                    phy, 1);
+                       }
 
                        bnx2x_warpcore_config_sfi(phy, params);
                        break;
@@ -5757,6 +5778,11 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
        rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, gp_speed,
                                         duplex);
 
+       /* In case of KR link down, start up the recovering procedure */
+       if ((!link_up) && (phy->media_type == ETH_PHY_KR) &&
+           (!(phy->flags & FLAGS_WC_DUAL_MODE)))
+               vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
+
        DP(NETIF_MSG_LINK, "duplex %x  flow_ctrl 0x%x link_status 0x%x\n",
                   vars->duplex, vars->flow_ctrl, vars->link_status);
        return rc;
@@ -6507,6 +6533,11 @@ static int bnx2x_link_initialize(struct link_params *params,
                        params->phy[INT_PHY].config_init(phy, params, vars);
        }
 
+       /* Re-read this value in case it was changed inside config_init due to
+        * limitations of optic module
+        */
+       vars->line_speed = params->phy[INT_PHY].req_line_speed;
+
        /* Init external phy*/
        if (non_ext_phy) {
                if (params->phy[INT_PHY].supported &
@@ -8080,7 +8111,10 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
                if (copper_module_type &
                    SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE) {
                        DP(NETIF_MSG_LINK, "Active Copper cable detected\n");
-                       check_limiting_mode = 1;
+                       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
+                               *edc_mode = EDC_MODE_ACTIVE_DAC;
+                       else
+                               check_limiting_mode = 1;
                } else if (copper_module_type &
                        SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
                                DP(NETIF_MSG_LINK,
@@ -8555,6 +8589,7 @@ static void bnx2x_warpcore_set_limiting_mode(struct link_params *params,
                mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT;
                break;
        case EDC_MODE_PASSIVE_DAC:
+       case EDC_MODE_ACTIVE_DAC:
                mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_DAC;
                break;
        default:
@@ -9730,32 +9765,41 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
                         MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL,
                         an_1000_val);
 
-       /* set 100 speed advertisement */
-       if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
-            (phy->speed_cap_mask &
-             (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
-              PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF))) {
-               an_10_100_val |= (1<<7);
-               /* Enable autoneg and restart autoneg for legacy speeds */
-               autoneg_val |= (1<<9 | 1<<12);
-
-               if (phy->req_duplex == DUPLEX_FULL)
+       /* Set 10/100 speed advertisement */
+       if (phy->req_line_speed == SPEED_AUTO_NEG) {
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL) {
+                       /* Enable autoneg and restart autoneg for legacy speeds
+                        */
+                       autoneg_val |= (1<<9 | 1<<12);
                        an_10_100_val |= (1<<8);
-               DP(NETIF_MSG_LINK, "Advertising 100M\n");
-       }
-       /* set 10 speed advertisement */
-       if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
-            (phy->speed_cap_mask &
-             (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
-              PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)) &&
-            (phy->supported &
-             (SUPPORTED_10baseT_Half |
-              SUPPORTED_10baseT_Full)))) {
-               an_10_100_val |= (1<<5);
-               autoneg_val |= (1<<9 | 1<<12);
-               if (phy->req_duplex == DUPLEX_FULL)
+                       DP(NETIF_MSG_LINK, "Advertising 100M-FD\n");
+               }
+
+               if (phy->speed_cap_mask &
+                   PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF) {
+                       /* Enable autoneg and restart autoneg for legacy speeds
+                        */
+                       autoneg_val |= (1<<9 | 1<<12);
+                       an_10_100_val |= (1<<7);
+                       DP(NETIF_MSG_LINK, "Advertising 100M-HD\n");
+               }
+
+               if ((phy->speed_cap_mask &
+                    PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
+                   (phy->supported & SUPPORTED_10baseT_Full)) {
                        an_10_100_val |= (1<<6);
-               DP(NETIF_MSG_LINK, "Advertising 10M\n");
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 10M-FD\n");
+               }
+
+               if ((phy->speed_cap_mask &
+                    PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF) &&
+                   (phy->supported & SUPPORTED_10baseT_Half)) {
+                       an_10_100_val |= (1<<5);
+                       autoneg_val |= (1<<9 | 1<<12);
+                       DP(NETIF_MSG_LINK, "Advertising 10M-HD\n");
+               }
        }
 
        /* Only 10/100 are allowed to work in FORCE mode */
@@ -13432,43 +13476,6 @@ static void bnx2x_sfp_tx_fault_detection(struct bnx2x_phy *phy,
                }
        }
 }
-static void bnx2x_disable_kr2(struct link_params *params,
-                             struct link_vars *vars,
-                             struct bnx2x_phy *phy)
-{
-       struct bnx2x *bp = params->bp;
-       int i;
-       static struct bnx2x_reg_set reg_set[] = {
-               /* Step 1 - Program the TX/RX alignment markers */
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0x7690},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xe647},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0xc4f0},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0x7690},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xe647},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0xc4f0},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000c},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6000},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0000},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0002},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x0000},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x0af7},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x0af7},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0002},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0000}
-       };
-       DP(NETIF_MSG_LINK, "Disabling 20G-KR2\n");
-
-       for (i = 0; i < ARRAY_SIZE(reg_set); i++)
-               bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
-                                reg_set[i].val);
-       vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
-       bnx2x_update_link_attr(params, vars->link_attr_sync);
-
-       vars->check_kr2_recovery_cnt = CHECK_KR2_RECOVERY_CNT;
-       /* Restart AN on leading lane */
-       bnx2x_warpcore_restart_AN_KR(phy, params);
-}
-
 static void bnx2x_kr2_recovery(struct link_params *params,
                               struct link_vars *vars,
                               struct bnx2x_phy *phy)
@@ -13546,6 +13553,8 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
                /* Disable KR2 on both lanes */
                DP(NETIF_MSG_LINK, "BP=0x%x, NP=0x%x\n", base_page, next_page);
                bnx2x_disable_kr2(params, vars, phy);
+               /* Restart AN on leading lane */
+               bnx2x_warpcore_restart_AN_KR(phy, params);
                return;
        }
 }
index 2f8dbbbd7a860ba21f1428a85fb0c6f89e143692..38bf99893c1d113b7e4ed7a19b95d00901b9e2ab 100644 (file)
@@ -4703,6 +4703,14 @@ bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print)
        attn.sig[3] = REG_RD(bp,
                MISC_REG_AEU_AFTER_INVERT_4_FUNC_0 +
                             port*4);
+       /* Since MCP attentions can't be disabled inside the block, we need to
+        * read AEU registers to see whether they're currently disabled
+        */
+       attn.sig[3] &= ((REG_RD(bp,
+                               !port ? MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0
+                                     : MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0) &
+                        MISC_AEU_ENABLE_MCP_PRTY_BITS) |
+                       ~MISC_AEU_ENABLE_MCP_PRTY_BITS);
 
        if (!CHIP_IS_E1x(bp))
                attn.sig[4] = REG_RD(bp,
@@ -5447,26 +5455,24 @@ static void bnx2x_timer(unsigned long data)
        if (IS_PF(bp) &&
            !BP_NOMCP(bp)) {
                int mb_idx = BP_FW_MB_IDX(bp);
-               u32 drv_pulse;
-               u32 mcp_pulse;
+               u16 drv_pulse;
+               u16 mcp_pulse;
 
                ++bp->fw_drv_pulse_wr_seq;
                bp->fw_drv_pulse_wr_seq &= DRV_PULSE_SEQ_MASK;
-               /* TBD - add SYSTEM_TIME */
                drv_pulse = bp->fw_drv_pulse_wr_seq;
                bnx2x_drv_pulse(bp);
 
                mcp_pulse = (SHMEM_RD(bp, func_mb[mb_idx].mcp_pulse_mb) &
                             MCP_PULSE_SEQ_MASK);
                /* The delta between driver pulse and mcp response
-                * should be 1 (before mcp response) or 0 (after mcp response)
+                * should not get too big. If the MFW is more than 5 pulses
+                * behind, we should worry about it enough to generate an error
+                * log.
                 */
-               if ((drv_pulse != mcp_pulse) &&
-                   (drv_pulse != ((mcp_pulse + 1) & MCP_PULSE_SEQ_MASK))) {
-                       /* someone lost a heartbeat... */
-                       BNX2X_ERR("drv_pulse (0x%x) != mcp_pulse (0x%x)\n",
+               if (((drv_pulse - mcp_pulse) & MCP_PULSE_SEQ_MASK) > 5)
+                       BNX2X_ERR("MFW seems hanged: drv_pulse (0x%x) != mcp_pulse (0x%x)\n",
                                  drv_pulse, mcp_pulse);
-               }
        }
 
        if (bp->state == BNX2X_STATE_OPEN)
@@ -8652,6 +8658,7 @@ u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode)
        else if (bp->wol) {
                u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
                u8 *mac_addr = bp->dev->dev_addr;
+               struct pci_dev *pdev = bp->pdev;
                u32 val;
                u16 pmc;
 
@@ -8668,9 +8675,9 @@ u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode)
                EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry + 4, val);
 
                /* Enable the PME and clear the status */
-               pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmc);
+               pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &pmc);
                pmc |= PCI_PM_CTRL_PME_ENABLE | PCI_PM_CTRL_PME_STATUS;
-               pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, pmc);
+               pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, pmc);
 
                reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_EN;
 
@@ -10399,7 +10406,7 @@ static void bnx2x_get_common_hwinfo(struct bnx2x *bp)
                break;
        }
 
-       pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc);
+       pci_read_config_word(bp->pdev, bp->pdev->pm_cap + PCI_PM_PMC, &pmc);
        bp->flags |= (pmc & PCI_PM_CAP_PME_D3cold) ? 0 : NO_WOL_FLAG;
 
        BNX2X_DEV_INFO("%sWoL capable\n",
@@ -12072,13 +12079,9 @@ static int bnx2x_set_coherency_mask(struct bnx2x *bp)
 {
        struct device *dev = &bp->pdev->dev;
 
-       if (dma_set_mask(dev, DMA_BIT_MASK(64)) == 0) {
+       if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)) == 0) {
                bp->flags |= USING_DAC_FLAG;
-               if (dma_set_coherent_mask(dev, DMA_BIT_MASK(64)) != 0) {
-                       dev_err(dev, "dma_set_coherent_mask failed, aborting\n");
-                       return -EIO;
-               }
-       } else if (dma_set_mask(dev, DMA_BIT_MASK(32)) != 0) {
+       } else if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)) != 0) {
                dev_err(dev, "System does not support DMA, aborting\n");
                return -EIO;
        }
@@ -12141,8 +12144,7 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev,
        }
 
        if (IS_PF(bp)) {
-               bp->pm_cap = pdev->pm_cap;
-               if (bp->pm_cap == 0) {
+               if (!pdev->pm_cap) {
                        dev_err(&bp->pdev->dev,
                                "Cannot find power management capability, aborting\n");
                        rc = -EIO;
@@ -13632,6 +13634,10 @@ void bnx2x_setup_cnic_info(struct bnx2x *bp)
        cp->fcoe_init_cid = BNX2X_FCOE_ETH_CID(bp);
        cp->iscsi_l2_cid = BNX2X_ISCSI_ETH_CID(bp);
 
+       DP(NETIF_MSG_IFUP, "BNX2X_1st_NON_L2_ETH_CID(bp) %x, cp->starting_cid %x, cp->fcoe_init_cid %x, cp->iscsi_l2_cid %x\n",
+          BNX2X_1st_NON_L2_ETH_CID(bp), cp->starting_cid, cp->fcoe_init_cid,
+          cp->iscsi_l2_cid);
+
        if (NO_ISCSI_OOO(bp))
                cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI_OOO;
 }
index 2604b6204abe03965cf0f89dd48b5a25bf00e7e1..9ad012bdd9151e44ce699b640e77273ad9901796 100644 (file)
@@ -1819,7 +1819,7 @@ bnx2x_get_vf_igu_cam_info(struct bnx2x *bp)
                fid = GET_FIELD((val), IGU_REG_MAPPING_MEMORY_FID);
                if (fid & IGU_FID_ENCODE_IS_PF)
                        current_pf = fid & IGU_FID_PF_NUM_MASK;
-               else if (current_pf == BP_ABS_FUNC(bp))
+               else if (current_pf == BP_FUNC(bp))
                        bnx2x_vf_set_igu_info(bp, sb_id,
                                              (fid & IGU_FID_VF_NUM_MASK));
                DP(BNX2X_MSG_IOV, "%s[%d], igu_sb_id=%d, msix=%d\n",
@@ -3180,6 +3180,7 @@ int bnx2x_enable_sriov(struct bnx2x *bp)
                /* set local queue arrays */
                vf->vfqs = &bp->vfdb->vfqs[qcount];
                qcount += vf_sb_count(vf);
+               bnx2x_iov_static_resc(bp, vf);
        }
 
        /* prepare msix vectors in VF configuration space */
@@ -3187,6 +3188,8 @@ int bnx2x_enable_sriov(struct bnx2x *bp)
                bnx2x_pretend_func(bp, HW_VF_HANDLE(bp, vf_idx));
                REG_WR(bp, PCICFG_OFFSET + GRC_CONFIG_REG_VF_MSIX_CONTROL,
                       num_vf_queues);
+               DP(BNX2X_MSG_IOV, "set msix vec num in VF %d cfg space to %d\n",
+                  vf_idx, num_vf_queues);
        }
        bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
 
index 6cfb8873245281a74222926b6052838d6df1eca0..da16953eb2ec58012f059273abf153c7e81293b9 100644 (file)
@@ -1765,28 +1765,28 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
                switch (mbx->first_tlv.tl.type) {
                case CHANNEL_TLV_ACQUIRE:
                        bnx2x_vf_mbx_acquire(bp, vf, mbx);
-                       break;
+                       return;
                case CHANNEL_TLV_INIT:
                        bnx2x_vf_mbx_init_vf(bp, vf, mbx);
-                       break;
+                       return;
                case CHANNEL_TLV_SETUP_Q:
                        bnx2x_vf_mbx_setup_q(bp, vf, mbx);
-                       break;
+                       return;
                case CHANNEL_TLV_SET_Q_FILTERS:
                        bnx2x_vf_mbx_set_q_filters(bp, vf, mbx);
-                       break;
+                       return;
                case CHANNEL_TLV_TEARDOWN_Q:
                        bnx2x_vf_mbx_teardown_q(bp, vf, mbx);
-                       break;
+                       return;
                case CHANNEL_TLV_CLOSE:
                        bnx2x_vf_mbx_close_vf(bp, vf, mbx);
-                       break;
+                       return;
                case CHANNEL_TLV_RELEASE:
                        bnx2x_vf_mbx_release_vf(bp, vf, mbx);
-                       break;
+                       return;
                case CHANNEL_TLV_UPDATE_RSS:
                        bnx2x_vf_mbx_update_rss(bp, vf, mbx);
-                       break;
+                       return;
                }
 
        } else {
@@ -1802,26 +1802,24 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
                for (i = 0; i < 20; i++)
                        DP_CONT(BNX2X_MSG_IOV, "%x ",
                                mbx->msg->req.tlv_buf_size.tlv_buffer[i]);
+       }
 
-               /* test whether we can respond to the VF (do we have an address
-                * for it?)
-                */
-               if (vf->state == VF_ACQUIRED || vf->state == VF_ENABLED) {
-                       /* mbx_resp uses the op_rc of the VF */
-                       vf->op_rc = PFVF_STATUS_NOT_SUPPORTED;
+       /* can we respond to VF (do we have an address for it?) */
+       if (vf->state == VF_ACQUIRED || vf->state == VF_ENABLED) {
+               /* mbx_resp uses the op_rc of the VF */
+               vf->op_rc = PFVF_STATUS_NOT_SUPPORTED;
 
-                       /* notify the VF that we do not support this request */
-                       bnx2x_vf_mbx_resp(bp, vf);
-               } else {
-                       /* can't send a response since this VF is unknown to us
-                        * just ack the FW to release the mailbox and unlock
-                        * the channel.
-                        */
-                       storm_memset_vf_mbx_ack(bp, vf->abs_vfid);
-                       mmiowb();
-                       bnx2x_unlock_vf_pf_channel(bp, vf,
-                                                  mbx->first_tlv.tl.type);
-               }
+               /* notify the VF that we do not support this request */
+               bnx2x_vf_mbx_resp(bp, vf);
+       } else {
+               /* can't send a response since this VF is unknown to us
+                * just ack the FW to release the mailbox and unlock
+                * the channel.
+                */
+               storm_memset_vf_mbx_ack(bp, vf->abs_vfid);
+               /* Firmware ack should be written before unlocking channel */
+               mmiowb();
+               bnx2x_unlock_vf_pf_channel(bp, vf, mbx->first_tlv.tl.type);
        }
 }
 
index 8142480d9770ff5f3aa19e4d24eaae615e4e75c4..99394bd49a139414776df9ff776c02b2fe6f3c26 100644 (file)
@@ -3135,6 +3135,7 @@ static void cnic_service_bnx2x_bh(unsigned long data)
 {
        struct cnic_dev *dev = (struct cnic_dev *) data;
        struct cnic_local *cp = dev->cnic_priv;
+       struct bnx2x *bp = netdev_priv(dev->netdev);
        u32 status_idx, new_status_idx;
 
        if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags)))
@@ -3146,7 +3147,7 @@ static void cnic_service_bnx2x_bh(unsigned long data)
                CNIC_WR16(dev, cp->kcq1.io_addr,
                          cp->kcq1.sw_prod_idx + MAX_KCQ_IDX);
 
-               if (cp->ethdev->drv_state & CNIC_DRV_STATE_NO_FCOE) {
+               if (!CNIC_SUPPORTS_FCOE(bp)) {
                        cp->arm_int(dev, status_idx);
                        break;
                }
@@ -5217,7 +5218,8 @@ static void cnic_init_rings(struct cnic_dev *dev)
                                "iSCSI CLIENT_SETUP did not complete\n");
                cnic_spq_completion(dev, DRV_CTL_RET_L2_SPQ_CREDIT_CMD, 1);
                cnic_ring_ctl(dev, cid, cli, 1);
-               *cid_ptr = cid;
+               *cid_ptr = cid >> 4;
+               *(cid_ptr + 1) = cid * bp->db_size;
        }
 }
 
index 5701f3d1a169a207440c3ec92da789d6ea948536..12d961c4ebcaf704e36b83c8624633c2fbd48dda 100644 (file)
@@ -3034,6 +3034,7 @@ static bool tg3_phy_led_bug(struct tg3 *tp)
 {
        switch (tg3_asic_rev(tp)) {
        case ASIC_REV_5719:
+       case ASIC_REV_5720:
                if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) &&
                    !tp->pci_fn)
                        return true;
@@ -16192,12 +16193,12 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent)
                         * So explicitly force the chip into D0 here.
                         */
                        pci_read_config_dword(tp->pdev,
-                                             tp->pm_cap + PCI_PM_CTRL,
+                                             tp->pdev->pm_cap + PCI_PM_CTRL,
                                              &pm_reg);
                        pm_reg &= ~PCI_PM_CTRL_STATE_MASK;
                        pm_reg |= PCI_PM_CTRL_PME_ENABLE | 0 /* D0 */;
                        pci_write_config_dword(tp->pdev,
-                                              tp->pm_cap + PCI_PM_CTRL,
+                                              tp->pdev->pm_cap + PCI_PM_CTRL,
                                               pm_reg);
 
                        /* Also, force SERR#/PERR# in PCI command. */
@@ -17346,7 +17347,6 @@ static int tg3_init_one(struct pci_dev *pdev,
        tp = netdev_priv(dev);
        tp->pdev = pdev;
        tp->dev = dev;
-       tp->pm_cap = pdev->pm_cap;
        tp->rx_mode = TG3_DEF_RX_MODE;
        tp->tx_mode = TG3_DEF_TX_MODE;
        tp->irq_sync = 1;
index ddb8be1298eab2b66eac319a4abce91a72da8896..70257808aa37deb3c2ff0511a16a6966a8d5f9c0 100644 (file)
@@ -3234,7 +3234,6 @@ struct tg3 {
        u8                              pci_lat_timer;
 
        int                             pci_fn;
-       int                             pm_cap;
        int                             msi_cap;
        int                             pcix_cap;
        int                             pcie_readrq;
index b78e69e0e52a291047e72c222530a1500e4ac003..45ce6e2214b3227c275c92d9bd8ece76bb478097 100644 (file)
@@ -3300,17 +3300,12 @@ bnad_pci_init(struct bnad *bnad,
        err = pci_request_regions(pdev, BNAD_NAME);
        if (err)
                goto disable_device;
-       if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) &&
-           !dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64))) {
+       if (!dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) {
                *using_dac = true;
        } else {
-               err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
-               if (err) {
-                       err = dma_set_coherent_mask(&pdev->dev,
-                                                   DMA_BIT_MASK(32));
-                       if (err)
-                               goto release_regions;
-               }
+               err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+               if (err)
+                       goto release_regions;
                *using_dac = false;
        }
        pci_set_master(pdev);
index 0d0665ca6f1914f77fa3aa23b68254d42fcd0c86..c73cabdbd4c08a22fd506eef8a219f02833fb4b3 100644 (file)
@@ -6149,8 +6149,10 @@ static int __init cxgb4_init_module(void)
                pr_warn("could not create debugfs entry, continuing\n");
 
        ret = pci_register_driver(&cxgb4_driver);
-       if (ret < 0)
+       if (ret < 0) {
                debugfs_remove(cxgb4_debugfs_root);
+               destroy_workqueue(workq);
+       }
 
        register_inet6addr_notifier(&cxgb4_inet6addr_notifier);
 
index 2db6c573cec7744c49d6cc205fce25476f0cc0ea..263b92c00cbfb34dbc3b1904cd2ddacafdeb48cc 100644 (file)
@@ -1321,7 +1321,7 @@ de4x5_open(struct net_device *dev)
     if (request_irq(dev->irq, de4x5_interrupt, IRQF_SHARED,
                                                     lp->adapter_name, dev)) {
        printk("de4x5_open(): Requested IRQ%d is busy - attemping FAST/SHARE...", dev->irq);
-       if (request_irq(dev->irq, de4x5_interrupt, IRQF_DISABLED | IRQF_SHARED,
+       if (request_irq(dev->irq, de4x5_interrupt, IRQF_SHARED,
                                                     lp->adapter_name, dev)) {
            printk("\n              Cannot get IRQ- reconfigure your hardware.\n");
            disable_ast(dev);
index ace5050dba3877ca8a3fe4995469ee3d16837c55..db020230bd0bba5ec72186bed9539357ec315abc 100644 (file)
@@ -88,6 +88,7 @@ static inline char *nic_name(struct pci_dev *pdev)
 #define BE_MIN_MTU             256
 
 #define BE_NUM_VLANS_SUPPORTED 64
+#define BE_UMC_NUM_VLANS_SUPPORTED     15
 #define BE_MAX_EQD             96u
 #define        BE_MAX_TX_FRAG_COUNT    30
 
@@ -333,6 +334,7 @@ enum vf_state {
 
 #define BE_FLAGS_LINK_STATUS_INIT              1
 #define BE_FLAGS_WORKER_SCHEDULED              (1 << 3)
+#define BE_FLAGS_VLAN_PROMISC                  (1 << 4)
 #define BE_FLAGS_NAPI_ENABLED                  (1 << 9)
 #define BE_UC_PMAC_COUNT               30
 #define BE_VF_UC_PMAC_COUNT            2
index 1ab5dab11eff07ab349a0cc795ef5986fe1e9010..bd0e0c0bbcd8e0e21d5295ef92aea6fb769d2c69 100644 (file)
@@ -180,6 +180,9 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
                        dev_err(&adapter->pdev->dev,
                                "opcode %d-%d failed:status %d-%d\n",
                                opcode, subsystem, compl_status, extd_status);
+
+                       if (extd_status == MCC_ADDL_STS_INSUFFICIENT_RESOURCES)
+                               return extd_status;
                }
        }
 done:
@@ -1812,6 +1815,12 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
        } else if (flags & IFF_ALLMULTI) {
                req->if_flags_mask = req->if_flags =
                                cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS);
+       } else if (flags & BE_FLAGS_VLAN_PROMISC) {
+               req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_VLAN_PROMISCUOUS);
+
+               if (value == ON)
+                       req->if_flags =
+                               cpu_to_le32(BE_IF_FLAGS_VLAN_PROMISCUOUS);
        } else {
                struct netdev_hw_addr *ha;
                int i = 0;
index d026226db88ccac0fcc70497ce2c8f6ef7b3e614..108ca8abf0af2321a6f5db5fe289af658b0bfcdf 100644 (file)
@@ -60,6 +60,8 @@ enum {
        MCC_STATUS_NOT_SUPPORTED = 66
 };
 
+#define MCC_ADDL_STS_INSUFFICIENT_RESOURCES    0x16
+
 #define CQE_STATUS_COMPL_MASK          0xFFFF
 #define CQE_STATUS_COMPL_SHIFT         0       /* bits 0 - 15 */
 #define CQE_STATUS_EXTD_MASK           0xFFFF
@@ -1791,7 +1793,7 @@ struct be_nic_res_desc {
        u8 acpi_params;
        u8 wol_param;
        u16 rsvd7;
-       u32 rsvd8[3];
+       u32 rsvd8[7];
 } __packed;
 
 struct be_cmd_req_get_func_config {
index 3224d28cdad4384d4322bd5765d503ef9ace1ca1..8ae79acd7db851c2867220aa5b72d5943fc14ec6 100644 (file)
@@ -855,11 +855,11 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
        unsigned int eth_hdr_len;
        struct iphdr *ip;
 
-       /* Lancer ASIC has a bug wherein packets that are 32 bytes or less
+       /* Lancer, SH-R ASICs have a bug wherein Packets that are 32 bytes or less
         * may cause a transmit stall on that port. So the work-around is to
-        * pad such packets to a 36-byte length.
+        * pad short packets (<= 32 bytes) to a 36-byte length.
         */
-       if (unlikely(lancer_chip(adapter) && skb->len <= 32)) {
+       if (unlikely(!BEx_chip(adapter) && skb->len <= 32)) {
                if (skb_padto(skb, 36))
                        goto tx_drop;
                skb->len = 36;
@@ -1013,18 +1013,40 @@ static int be_vid_config(struct be_adapter *adapter)
        status = be_cmd_vlan_config(adapter, adapter->if_handle,
                                    vids, num, 1, 0);
 
-       /* Set to VLAN promisc mode as setting VLAN filter failed */
        if (status) {
-               dev_info(&adapter->pdev->dev, "Exhausted VLAN HW filters.\n");
-               dev_info(&adapter->pdev->dev, "Disabling HW VLAN filtering.\n");
-               goto set_vlan_promisc;
+               /* Set to VLAN promisc mode as setting VLAN filter failed */
+               if (status == MCC_ADDL_STS_INSUFFICIENT_RESOURCES)
+                       goto set_vlan_promisc;
+               dev_err(&adapter->pdev->dev,
+                       "Setting HW VLAN filtering failed.\n");
+       } else {
+               if (adapter->flags & BE_FLAGS_VLAN_PROMISC) {
+                       /* hw VLAN filtering re-enabled. */
+                       status = be_cmd_rx_filter(adapter,
+                                                 BE_FLAGS_VLAN_PROMISC, OFF);
+                       if (!status) {
+                               dev_info(&adapter->pdev->dev,
+                                        "Disabling VLAN Promiscuous mode.\n");
+                               adapter->flags &= ~BE_FLAGS_VLAN_PROMISC;
+                               dev_info(&adapter->pdev->dev,
+                                        "Re-Enabling HW VLAN filtering\n");
+                       }
+               }
        }
 
        return status;
 
 set_vlan_promisc:
-       status = be_cmd_vlan_config(adapter, adapter->if_handle,
-                                   NULL, 0, 1, 1);
+       dev_warn(&adapter->pdev->dev, "Exhausted VLAN HW filters.\n");
+
+       status = be_cmd_rx_filter(adapter, BE_FLAGS_VLAN_PROMISC, ON);
+       if (!status) {
+               dev_info(&adapter->pdev->dev, "Enable VLAN Promiscuous mode\n");
+               dev_info(&adapter->pdev->dev, "Disabling HW VLAN filtering\n");
+               adapter->flags |= BE_FLAGS_VLAN_PROMISC;
+       } else
+               dev_err(&adapter->pdev->dev,
+                       "Failed to enable VLAN Promiscuous mode.\n");
        return status;
 }
 
@@ -1033,10 +1055,6 @@ static int be_vlan_add_vid(struct net_device *netdev, __be16 proto, u16 vid)
        struct be_adapter *adapter = netdev_priv(netdev);
        int status = 0;
 
-       if (!lancer_chip(adapter) && !be_physfn(adapter)) {
-               status = -EINVAL;
-               goto ret;
-       }
 
        /* Packets with VID 0 are always received by Lancer by default */
        if (lancer_chip(adapter) && vid == 0)
@@ -1059,11 +1077,6 @@ static int be_vlan_rem_vid(struct net_device *netdev, __be16 proto, u16 vid)
        struct be_adapter *adapter = netdev_priv(netdev);
        int status = 0;
 
-       if (!lancer_chip(adapter) && !be_physfn(adapter)) {
-               status = -EINVAL;
-               goto ret;
-       }
-
        /* Packets with VID 0 are always received by Lancer by default */
        if (lancer_chip(adapter) && vid == 0)
                goto ret;
@@ -1188,8 +1201,8 @@ static int be_get_vf_config(struct net_device *netdev, int vf,
 
        vi->vf = vf;
        vi->tx_rate = vf_cfg->tx_rate;
-       vi->vlan = vf_cfg->vlan_tag;
-       vi->qos = 0;
+       vi->vlan = vf_cfg->vlan_tag & VLAN_VID_MASK;
+       vi->qos = vf_cfg->vlan_tag >> VLAN_PRIO_SHIFT;
        memcpy(&vi->mac, vf_cfg->mac_addr, ETH_ALEN);
 
        return 0;
@@ -1199,28 +1212,29 @@ static int be_set_vf_vlan(struct net_device *netdev,
                        int vf, u16 vlan, u8 qos)
 {
        struct be_adapter *adapter = netdev_priv(netdev);
+       struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf];
        int status = 0;
 
        if (!sriov_enabled(adapter))
                return -EPERM;
 
-       if (vf >= adapter->num_vfs || vlan > 4095)
+       if (vf >= adapter->num_vfs || vlan > 4095 || qos > 7)
                return -EINVAL;
 
-       if (vlan) {
-               if (adapter->vf_cfg[vf].vlan_tag != vlan) {
+       if (vlan || qos) {
+               vlan |= qos << VLAN_PRIO_SHIFT;
+               if (vf_cfg->vlan_tag != vlan) {
                        /* If this is new value, program it. Else skip. */
-                       adapter->vf_cfg[vf].vlan_tag = vlan;
-
-                       status = be_cmd_set_hsw_config(adapter, vlan,
-                               vf + 1, adapter->vf_cfg[vf].if_handle, 0);
+                       vf_cfg->vlan_tag = vlan;
+                       status = be_cmd_set_hsw_config(adapter, vlan, vf + 1,
+                                                      vf_cfg->if_handle, 0);
                }
        } else {
                /* Reset Transparent Vlan Tagging. */
-               adapter->vf_cfg[vf].vlan_tag = 0;
-               vlan = adapter->vf_cfg[vf].def_vid;
+               vf_cfg->vlan_tag = 0;
+               vlan = vf_cfg->def_vid;
                status = be_cmd_set_hsw_config(adapter, vlan, vf + 1,
-                       adapter->vf_cfg[vf].if_handle, 0);
+                                              vf_cfg->if_handle, 0);
        }
 
 
@@ -2802,7 +2816,7 @@ static int be_vfs_if_create(struct be_adapter *adapter)
        struct be_resources res = {0};
        struct be_vf_cfg *vf_cfg;
        u32 cap_flags, en_flags, vf;
-       int status;
+       int status = 0;
 
        cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
                    BE_IF_FLAGS_MULTICAST;
@@ -2963,6 +2977,8 @@ static void BEx_get_resources(struct be_adapter *adapter,
 
        if (adapter->function_mode & FLEX10_MODE)
                res->max_vlans = BE_NUM_VLANS_SUPPORTED/8;
+       else if (adapter->function_mode & UMC_ENABLED)
+               res->max_vlans = BE_UMC_NUM_VLANS_SUPPORTED;
        else
                res->max_vlans = BE_NUM_VLANS_SUPPORTED;
        res->max_mcast_mac = BE_MAX_MC;
@@ -4335,19 +4351,11 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
        adapter->netdev = netdev;
        SET_NETDEV_DEV(netdev, &pdev->dev);
 
-       status = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
+       status = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
        if (!status) {
-               status = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
-               if (status < 0) {
-                       dev_err(&pdev->dev, "dma_set_coherent_mask failed\n");
-                       goto free_netdev;
-               }
                netdev->features |= NETIF_F_HIGHDMA;
        } else {
-               status = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
-               if (!status)
-                       status = dma_set_coherent_mask(&pdev->dev,
-                                                      DMA_BIT_MASK(32));
+               status = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
                if (status) {
                        dev_err(&pdev->dev, "Could not set PCI DMA Mask\n");
                        goto free_netdev;
index f9aacf5d85230c67fadaa9b892f9765da30171a7..b2793b91cc553e41e80170ac791d10b83f0e776d 100644 (file)
@@ -2199,7 +2199,7 @@ fec_probe(struct platform_device *pdev)
                        goto failed_irq;
                }
                ret = devm_request_irq(&pdev->dev, irq, fec_enet_interrupt,
-                                      IRQF_DISABLED, pdev->name, ndev);
+                                      0, pdev->name, ndev);
                if (ret)
                        goto failed_irq;
        }
index 098f133908ae016058f326225e2ed58b9709d592..e006a09ba8990050f3bc9a91e101ae8455419a87 100644 (file)
@@ -452,7 +452,9 @@ static int gianfar_ptp_probe(struct platform_device *dev)
        err = -ENODEV;
 
        etsects->caps = ptp_gianfar_caps;
-       etsects->cksel = DEFAULT_CKSEL;
+
+       if (get_of_u32(node, "fsl,cksel", &etsects->cksel))
+               etsects->cksel = DEFAULT_CKSEL;
 
        if (get_of_u32(node, "fsl,tclk-period", &etsects->tclk_period) ||
            get_of_u32(node, "fsl,tmr-prsc", &etsects->tmr_prsc) ||
index e3c7c697fc45c2e1c5670cdc6a04b6d93083a40c..91227d03274e02685d5e96fe6096e56e6af999eb 100644 (file)
@@ -1097,7 +1097,7 @@ static int hp100_open(struct net_device *dev)
        /* New: if bus is PCI or EISA, interrupts might be shared interrupts */
        if (request_irq(dev->irq, hp100_interrupt,
                        lp->bus == HP100_BUS_PCI || lp->bus ==
-                       HP100_BUS_EISA ? IRQF_SHARED : IRQF_DISABLED,
+                       HP100_BUS_EISA ? IRQF_SHARED : 0,
                        "hp100", dev)) {
                printk("hp100: %s: unable to get IRQ %d\n", dev->name, dev->irq);
                return -EAGAIN;
index 35853b43d66e860bd24e5bad2265b6dae9c9f7cc..2d1c6bdd36189f9f595ada15599301ce992330a9 100644 (file)
@@ -102,6 +102,19 @@ static int ehea_probe_adapter(struct platform_device *dev);
 
 static int ehea_remove(struct platform_device *dev);
 
+static struct of_device_id ehea_module_device_table[] = {
+       {
+               .name = "lhea",
+               .compatible = "IBM,lhea",
+       },
+       {
+               .type = "network",
+               .compatible = "IBM,lhea-ethernet",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, ehea_module_device_table);
+
 static struct of_device_id ehea_device_table[] = {
        {
                .name = "lhea",
@@ -109,7 +122,6 @@ static struct of_device_id ehea_device_table[] = {
        },
        {},
 };
-MODULE_DEVICE_TABLE(of, ehea_device_table);
 
 static struct platform_driver ehea_driver = {
        .driver = {
@@ -1285,7 +1297,7 @@ static int ehea_reg_interrupts(struct net_device *dev)
 
        ret = ibmebus_request_irq(port->qp_eq->attr.ist1,
                                  ehea_qp_aff_irq_handler,
-                                 IRQF_DISABLED, port->int_aff_name, port);
+                                 0, port->int_aff_name, port);
        if (ret) {
                netdev_err(dev, "failed registering irq for qp_aff_irq_handler:ist=%X\n",
                           port->qp_eq->attr.ist1);
@@ -1303,8 +1315,7 @@ static int ehea_reg_interrupts(struct net_device *dev)
                         "%s-queue%d", dev->name, i);
                ret = ibmebus_request_irq(pr->eq->attr.ist1,
                                          ehea_recv_irq_handler,
-                                         IRQF_DISABLED, pr->int_send_name,
-                                         pr);
+                                         0, pr->int_send_name, pr);
                if (ret) {
                        netdev_err(dev, "failed registering irq for ehea_queue port_res_nr:%d, ist=%X\n",
                                   i, pr->eq->attr.ist1);
@@ -3320,7 +3331,7 @@ static int ehea_probe_adapter(struct platform_device *dev)
        }
 
        ret = ibmebus_request_irq(adapter->neq->attr.ist1,
-                                 ehea_interrupt_neq, IRQF_DISABLED,
+                                 ehea_interrupt_neq, 0,
                                  "ehea_neq", adapter);
        if (ret) {
                dev_err(&dev->dev, "requesting NEQ IRQ failed\n");
index 59ad007dd5aa09a6123cbd25db7c7b8f4e06f1b7..34672f87726cb7b9ab0cdd1ac294b52a031ba4c8 100644 (file)
@@ -1018,19 +1018,14 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         */
        pci_using_dac = 0;
        if ((hw->bus_type == e1000_bus_type_pcix) &&
-           !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
-               /* according to DMA-API-HOWTO, coherent calls will always
-                * succeed if the set call did
-                */
-               dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
+           !dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) {
                pci_using_dac = 1;
        } else {
-               err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+               err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
                if (err) {
                        pr_err("No usable DMA config, aborting\n");
                        goto err_dma;
                }
-               dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
        }
 
        netdev->netdev_ops = &e1000_netdev_ops;
index a8633b8f0ac5aaff57b2be97d8e0ac5dfe3ff36a..d14c8f53384cd415c3933015c02bf9d2a369ba11 100644 (file)
@@ -922,6 +922,14 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
                        else
                                mask &= ~(1 << 30);
                }
+               if (mac->type == e1000_pch2lan) {
+                       /* SHRAH[0,1,2] different than previous */
+                       if (i == 7)
+                               mask &= 0xFFF4FFFF;
+                       /* SHRAH[3] different than SHRAH[0,1,2] */
+                       if (i == 10)
+                               mask |= (1 << 30);
+               }
 
                REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1), mask,
                                       0xFFFFFFFF);
index af08188d7e624471ed3e8b87df7d39fd24ba3815..42f0f6717511c21bb0f16edbeee050cc4878db96 100644 (file)
@@ -1371,7 +1371,10 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index)
                return;
        }
 
-       if (index < hw->mac.rar_entry_count) {
+       /* RAR[1-6] are owned by manageability.  Skip those and program the
+        * next address into the SHRA register array.
+        */
+       if (index < (u32)(hw->mac.rar_entry_count - 6)) {
                s32 ret_val;
 
                ret_val = e1000_acquire_swflag_ich8lan(hw);
@@ -1962,8 +1965,8 @@ void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw)
        if (ret_val)
                goto release;
 
-       /* Copy both RAL/H (rar_entry_count) and SHRAL/H (+4) to PHY */
-       for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
+       /* Copy both RAL/H (rar_entry_count) and SHRAL/H to PHY */
+       for (i = 0; i < (hw->mac.rar_entry_count); i++) {
                mac_reg = er32(RAL(i));
                hw->phy.ops.write_reg_page(hw, BM_RAR_L(i),
                                           (u16)(mac_reg & 0xFFFF));
@@ -2007,10 +2010,10 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
                return ret_val;
 
        if (enable) {
-               /* Write Rx addresses (rar_entry_count for RAL/H, +4 for
+               /* Write Rx addresses (rar_entry_count for RAL/H, and
                 * SHRAL/H) and initial CRC values to the MAC
                 */
-               for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
+               for (i = 0; i < hw->mac.rar_entry_count; i++) {
                        u8 mac_addr[ETH_ALEN] = { 0 };
                        u32 addr_high, addr_low;
 
index 59865695b2826a388b721b2313253e25d86a7c94..217090df33e788d46603f1c0369a2cf4e8041719 100644 (file)
@@ -98,7 +98,7 @@
 #define PCIE_ICH8_SNOOP_ALL    PCIE_NO_SNOOP_ALL
 
 #define E1000_ICH_RAR_ENTRIES  7
-#define E1000_PCH2_RAR_ENTRIES 5       /* RAR[0], SHRA[0-3] */
+#define E1000_PCH2_RAR_ENTRIES 11      /* RAR[0-6], SHRA[0-3] */
 #define E1000_PCH_LPT_RAR_ENTRIES      12      /* RAR[0], SHRA[0-10] */
 
 #define PHY_PAGE_SHIFT         5
index e87e9b01f404446dfca553146fa4734c2af45f79..aedd5736a87d53862fa2be4176e9762fcd8df18a 100644 (file)
@@ -4868,7 +4868,7 @@ static void e1000_watchdog_task(struct work_struct *work)
                         */
                        if ((hw->phy.type == e1000_phy_igp_3 ||
                             hw->phy.type == e1000_phy_bm) &&
-                           (hw->mac.autoneg == true) &&
+                           hw->mac.autoneg &&
                            (adapter->link_speed == SPEED_10 ||
                             adapter->link_speed == SPEED_100) &&
                            (adapter->link_duplex == HALF_DUPLEX)) {
@@ -6553,21 +6553,15 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                return err;
 
        pci_using_dac = 0;
-       err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
+       err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
        if (!err) {
-               err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
-               if (!err)
-                       pci_using_dac = 1;
+               pci_using_dac = 1;
        } else {
-               err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+               err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
                if (err) {
-                       err = dma_set_coherent_mask(&pdev->dev,
-                                                   DMA_BIT_MASK(32));
-                       if (err) {
-                               dev_err(&pdev->dev,
-                                       "No usable DMA configuration, aborting\n");
-                               goto err_dma;
-                       }
+                       dev_err(&pdev->dev,
+                               "No usable DMA configuration, aborting\n");
+                       goto err_dma;
                }
        }
 
index 0c524fa9f8111a092c07d69a442c75dea43f0f42..cfef7fc32cdd4643382f6d0125589fd1e3de6a95 100644 (file)
@@ -701,8 +701,7 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
 
        details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use);
        if (cmd_details) {
-               memcpy(details, cmd_details,
-                      sizeof(struct i40e_asq_cmd_details));
+               *details = *cmd_details;
 
                /* If the cmd_details are defined copy the cookie.  The
                 * cpu_to_le32 is not needed here because the data is ignored
@@ -760,7 +759,7 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
        desc_on_ring = I40E_ADMINQ_DESC(hw->aq.asq, hw->aq.asq.next_to_use);
 
        /* if the desc is available copy the temp desc to the right place */
-       memcpy(desc_on_ring, desc, sizeof(struct i40e_aq_desc));
+       *desc_on_ring = *desc;
 
        /* if buff is not NULL assume indirect command */
        if (buff != NULL) {
@@ -807,7 +806,7 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
 
        /* if ready, copy the desc back to temp */
        if (i40e_asq_done(hw)) {
-               memcpy(desc, desc_on_ring, sizeof(struct i40e_aq_desc));
+               *desc = *desc_on_ring;
                if (buff != NULL)
                        memcpy(buff, dma_buff->va, buff_size);
                retval = le16_to_cpu(desc->retval);
index c21df7bc3b1dd9b348050c1593866b33e42c7cf6..1e4ea134975ac43e8288132e6e4b93bacb2f4b7e 100644 (file)
@@ -507,7 +507,7 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
 
        /* save link status information */
        if (link)
-               memcpy(link, hw_link_info, sizeof(struct i40e_link_status));
+               *link = *hw_link_info;
 
        /* flag cleared so helper functions don't call AQ again */
        hw->phy.get_link_info = false;
index 601d482694ea8486273371a6cb6d4b0a968cd33b..221aa4795017649ccdd57accb01520c4bccb42e8 100644 (file)
@@ -101,10 +101,10 @@ int i40e_allocate_dma_mem_d(struct i40e_hw *hw, struct i40e_dma_mem *mem,
        mem->size = ALIGN(size, alignment);
        mem->va = dma_zalloc_coherent(&pf->pdev->dev, mem->size,
                                      &mem->pa, GFP_KERNEL);
-       if (mem->va)
-               return 0;
+       if (!mem->va)
+               return -ENOMEM;
 
-       return -ENOMEM;
+       return 0;
 }
 
 /**
@@ -136,10 +136,10 @@ int i40e_allocate_virt_mem_d(struct i40e_hw *hw, struct i40e_virt_mem *mem,
        mem->size = size;
        mem->va = kzalloc(size, GFP_KERNEL);
 
-       if (mem->va)
-               return 0;
+       if (!mem->va)
+               return -ENOMEM;
 
-       return -ENOMEM;
+       return 0;
 }
 
 /**
@@ -174,8 +174,7 @@ static int i40e_get_lump(struct i40e_pf *pf, struct i40e_lump_tracking *pile,
                         u16 needed, u16 id)
 {
        int ret = -ENOMEM;
-       int i = 0;
-       int j = 0;
+       int i, j;
 
        if (!pile || needed == 0 || id >= I40E_PILE_VALID_BIT) {
                dev_info(&pf->pdev->dev,
@@ -186,7 +185,7 @@ static int i40e_get_lump(struct i40e_pf *pf, struct i40e_lump_tracking *pile,
 
        /* start the linear search with an imperfect hint */
        i = pile->search_hint;
-       while (i < pile->num_entries && ret < 0) {
+       while (i < pile->num_entries) {
                /* skip already allocated entries */
                if (pile->list[i] & I40E_PILE_VALID_BIT) {
                        i++;
@@ -205,6 +204,7 @@ static int i40e_get_lump(struct i40e_pf *pf, struct i40e_lump_tracking *pile,
                                pile->list[i+j] = id | I40E_PILE_VALID_BIT;
                        ret = i;
                        pile->search_hint = i + j;
+                       break;
                } else {
                        /* not enough, so skip over it and continue looking */
                        i += j;
@@ -1388,7 +1388,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
        bool add_happened = false;
        int filter_list_len = 0;
        u32 changed_flags = 0;
-       i40e_status ret = 0;
+       i40e_status aq_ret = 0;
        struct i40e_pf *pf;
        int num_add = 0;
        int num_del = 0;
@@ -1449,28 +1449,28 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
 
                        /* flush a full buffer */
                        if (num_del == filter_list_len) {
-                               ret = i40e_aq_remove_macvlan(&pf->hw,
+                               aq_ret = i40e_aq_remove_macvlan(&pf->hw,
                                            vsi->seid, del_list, num_del,
                                            NULL);
                                num_del = 0;
                                memset(del_list, 0, sizeof(*del_list));
 
-                               if (ret)
+                               if (aq_ret)
                                        dev_info(&pf->pdev->dev,
                                                 "ignoring delete macvlan error, err %d, aq_err %d while flushing a full buffer\n",
-                                                ret,
+                                                aq_ret,
                                                 pf->hw.aq.asq_last_status);
                        }
                }
                if (num_del) {
-                       ret = i40e_aq_remove_macvlan(&pf->hw, vsi->seid,
+                       aq_ret = i40e_aq_remove_macvlan(&pf->hw, vsi->seid,
                                                     del_list, num_del, NULL);
                        num_del = 0;
 
-                       if (ret)
+                       if (aq_ret)
                                dev_info(&pf->pdev->dev,
                                         "ignoring delete macvlan error, err %d, aq_err %d\n",
-                                        ret, pf->hw.aq.asq_last_status);
+                                        aq_ret, pf->hw.aq.asq_last_status);
                }
 
                kfree(del_list);
@@ -1515,32 +1515,30 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
 
                        /* flush a full buffer */
                        if (num_add == filter_list_len) {
-                               ret = i40e_aq_add_macvlan(&pf->hw,
-                                                         vsi->seid,
-                                                         add_list,
-                                                         num_add,
-                                                         NULL);
+                               aq_ret = i40e_aq_add_macvlan(&pf->hw, vsi->seid,
+                                                            add_list, num_add,
+                                                            NULL);
                                num_add = 0;
 
-                               if (ret)
+                               if (aq_ret)
                                        break;
                                memset(add_list, 0, sizeof(*add_list));
                        }
                }
                if (num_add) {
-                       ret = i40e_aq_add_macvlan(&pf->hw, vsi->seid,
-                                                 add_list, num_add, NULL);
+                       aq_ret = i40e_aq_add_macvlan(&pf->hw, vsi->seid,
+                                                    add_list, num_add, NULL);
                        num_add = 0;
                }
                kfree(add_list);
                add_list = NULL;
 
-               if (add_happened && (!ret)) {
+               if (add_happened && (!aq_ret)) {
                        /* do nothing */;
-               } else if (add_happened && (ret)) {
+               } else if (add_happened && (aq_ret)) {
                        dev_info(&pf->pdev->dev,
                                 "add filter failed, err %d, aq_err %d\n",
-                                ret, pf->hw.aq.asq_last_status);
+                                aq_ret, pf->hw.aq.asq_last_status);
                        if ((pf->hw.aq.asq_last_status == I40E_AQ_RC_ENOSPC) &&
                            !test_bit(__I40E_FILTER_OVERFLOW_PROMISC,
                                      &vsi->state)) {
@@ -1556,28 +1554,27 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
        if (changed_flags & IFF_ALLMULTI) {
                bool cur_multipromisc;
                cur_multipromisc = !!(vsi->current_netdev_flags & IFF_ALLMULTI);
-               ret = i40e_aq_set_vsi_multicast_promiscuous(&vsi->back->hw,
-                                                           vsi->seid,
-                                                           cur_multipromisc,
-                                                           NULL);
-               if (ret)
+               aq_ret = i40e_aq_set_vsi_multicast_promiscuous(&vsi->back->hw,
+                                                              vsi->seid,
+                                                              cur_multipromisc,
+                                                              NULL);
+               if (aq_ret)
                        dev_info(&pf->pdev->dev,
                                 "set multi promisc failed, err %d, aq_err %d\n",
-                                ret, pf->hw.aq.asq_last_status);
+                                aq_ret, pf->hw.aq.asq_last_status);
        }
        if ((changed_flags & IFF_PROMISC) || promisc_forced_on) {
                bool cur_promisc;
                cur_promisc = (!!(vsi->current_netdev_flags & IFF_PROMISC) ||
                               test_bit(__I40E_FILTER_OVERFLOW_PROMISC,
                                        &vsi->state));
-               ret = i40e_aq_set_vsi_unicast_promiscuous(&vsi->back->hw,
-                                                         vsi->seid,
-                                                         cur_promisc,
-                                                         NULL);
-               if (ret)
+               aq_ret = i40e_aq_set_vsi_unicast_promiscuous(&vsi->back->hw,
+                                                            vsi->seid,
+                                                            cur_promisc, NULL);
+               if (aq_ret)
                        dev_info(&pf->pdev->dev,
                                 "set uni promisc failed, err %d, aq_err %d\n",
-                                ret, pf->hw.aq.asq_last_status);
+                                aq_ret, pf->hw.aq.asq_last_status);
        }
 
        clear_bit(__I40E_CONFIG_BUSY, &vsi->state);
@@ -1790,6 +1787,8 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)
  * i40e_vsi_kill_vlan - Remove vsi membership for given vlan
  * @vsi: the vsi being configured
  * @vid: vlan id to be removed (0 = untagged only , -1 = any)
+ *
+ * Return: 0 on success or negative otherwise
  **/
 int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)
 {
@@ -1863,37 +1862,39 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)
  * i40e_vlan_rx_add_vid - Add a vlan id filter to HW offload
  * @netdev: network interface to be adjusted
  * @vid: vlan id to be added
+ *
+ * net_device_ops implementation for adding vlan ids
  **/
 static int i40e_vlan_rx_add_vid(struct net_device *netdev,
                                __always_unused __be16 proto, u16 vid)
 {
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_vsi *vsi = np->vsi;
-       int ret;
+       int ret = 0;
 
        if (vid > 4095)
-               return 0;
+               return -EINVAL;
+
+       netdev_info(netdev, "adding %pM vid=%d\n", netdev->dev_addr, vid);
 
-       netdev_info(vsi->netdev, "adding %pM vid=%d\n",
-                   netdev->dev_addr, vid);
        /* If the network stack called us with vid = 0, we should
         * indicate to i40e_vsi_add_vlan() that we want to receive
         * any traffic (i.e. with any vlan tag, or untagged)
         */
        ret = i40e_vsi_add_vlan(vsi, vid ? vid : I40E_VLAN_ANY);
 
-       if (!ret) {
-               if (vid < VLAN_N_VID)
-                       set_bit(vid, vsi->active_vlans);
-       }
+       if (!ret && (vid < VLAN_N_VID))
+               set_bit(vid, vsi->active_vlans);
 
-       return 0;
+       return ret;
 }
 
 /**
  * i40e_vlan_rx_kill_vid - Remove a vlan id filter from HW offload
  * @netdev: network interface to be adjusted
  * @vid: vlan id to be removed
+ *
+ * net_device_ops implementation for adding vlan ids
  **/
 static int i40e_vlan_rx_kill_vid(struct net_device *netdev,
                                 __always_unused __be16 proto, u16 vid)
@@ -1901,15 +1902,16 @@ static int i40e_vlan_rx_kill_vid(struct net_device *netdev,
        struct i40e_netdev_priv *np = netdev_priv(netdev);
        struct i40e_vsi *vsi = np->vsi;
 
-       netdev_info(vsi->netdev, "removing %pM vid=%d\n",
-                   netdev->dev_addr, vid);
+       netdev_info(netdev, "removing %pM vid=%d\n", netdev->dev_addr, vid);
+
        /* return code is ignored as there is nothing a user
         * can do about failure to remove and a log message was
-        * already printed from another function
+        * already printed from the other function
         */
        i40e_vsi_kill_vlan(vsi, vid);
 
        clear_bit(vid, vsi->active_vlans);
+
        return 0;
 }
 
@@ -1936,10 +1938,10 @@ static void i40e_restore_vlan(struct i40e_vsi *vsi)
  * @vsi: the vsi being adjusted
  * @vid: the vlan id to set as a PVID
  **/
-i40e_status i40e_vsi_add_pvid(struct i40e_vsi *vsi, u16 vid)
+int i40e_vsi_add_pvid(struct i40e_vsi *vsi, u16 vid)
 {
        struct i40e_vsi_context ctxt;
-       i40e_status ret;
+       i40e_status aq_ret;
 
        vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
        vsi->info.pvid = cpu_to_le16(vid);
@@ -1948,14 +1950,15 @@ i40e_status i40e_vsi_add_pvid(struct i40e_vsi *vsi, u16 vid)
 
        ctxt.seid = vsi->seid;
        memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
-       ret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL);
-       if (ret) {
+       aq_ret = i40e_aq_update_vsi_params(&vsi->back->hw, &ctxt, NULL);
+       if (aq_ret) {
                dev_info(&vsi->back->pdev->dev,
                         "%s: update vsi failed, aq_err=%d\n",
                         __func__, vsi->back->hw.aq.asq_last_status);
+               return -ENOENT;
        }
 
-       return ret;
+       return 0;
 }
 
 /**
@@ -3326,7 +3329,8 @@ static void i40e_pf_unquiesce_all_vsi(struct i40e_pf *pf)
  **/
 static u8 i40e_dcb_get_num_tc(struct i40e_dcbx_config *dcbcfg)
 {
-       int num_tc = 0, i;
+       u8 num_tc = 0;
+       int i;
 
        /* Scan the ETS Config Priority Table to find
         * traffic class enabled for a given priority
@@ -3341,9 +3345,7 @@ static u8 i40e_dcb_get_num_tc(struct i40e_dcbx_config *dcbcfg)
        /* Traffic class index starts from zero so
         * increment to return the actual count
         */
-       num_tc++;
-
-       return num_tc;
+       return num_tc + 1;
 }
 
 /**
@@ -3451,28 +3453,27 @@ static int i40e_vsi_get_bw_info(struct i40e_vsi *vsi)
        struct i40e_aqc_query_vsi_bw_config_resp bw_config = {0};
        struct i40e_pf *pf = vsi->back;
        struct i40e_hw *hw = &pf->hw;
+       i40e_status aq_ret;
        u32 tc_bw_max;
-       int ret;
        int i;
 
        /* Get the VSI level BW configuration */
-       ret = i40e_aq_query_vsi_bw_config(hw, vsi->seid, &bw_config, NULL);
-       if (ret) {
+       aq_ret = i40e_aq_query_vsi_bw_config(hw, vsi->seid, &bw_config, NULL);
+       if (aq_ret) {
                dev_info(&pf->pdev->dev,
                         "couldn't get pf vsi bw config, err %d, aq_err %d\n",
-                        ret, pf->hw.aq.asq_last_status);
-               return ret;
+                        aq_ret, pf->hw.aq.asq_last_status);
+               return -EINVAL;
        }
 
        /* Get the VSI level BW configuration per TC */
-       ret = i40e_aq_query_vsi_ets_sla_config(hw, vsi->seid,
-                                              &bw_ets_config,
-                                              NULL);
-       if (ret) {
+       aq_ret = i40e_aq_query_vsi_ets_sla_config(hw, vsi->seid, &bw_ets_config,
+                                                 NULL);
+       if (aq_ret) {
                dev_info(&pf->pdev->dev,
                         "couldn't get pf vsi ets bw config, err %d, aq_err %d\n",
-                        ret, pf->hw.aq.asq_last_status);
-               return ret;
+                        aq_ret, pf->hw.aq.asq_last_status);
+               return -EINVAL;
        }
 
        if (bw_config.tc_valid_bits != bw_ets_config.tc_valid_bits) {
@@ -3494,7 +3495,8 @@ static int i40e_vsi_get_bw_info(struct i40e_vsi *vsi)
                /* 3 bits out of 4 for each TC */
                vsi->bw_ets_max_quanta[i] = (u8)((tc_bw_max >> (i*4)) & 0x7);
        }
-       return ret;
+
+       return 0;
 }
 
 /**
@@ -3505,30 +3507,30 @@ static int i40e_vsi_get_bw_info(struct i40e_vsi *vsi)
  *
  * Returns 0 on success, negative value on failure
  **/
-static int i40e_vsi_configure_bw_alloc(struct i40e_vsi *vsi,
-                                      u8 enabled_tc,
+static int i40e_vsi_configure_bw_alloc(struct i40e_vsi *vsi, u8 enabled_tc,
                                       u8 *bw_share)
 {
        struct i40e_aqc_configure_vsi_tc_bw_data bw_data;
-       int i, ret = 0;
+       i40e_status aq_ret;
+       int i;
 
        bw_data.tc_valid_bits = enabled_tc;
        for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
                bw_data.tc_bw_credits[i] = bw_share[i];
 
-       ret = i40e_aq_config_vsi_tc_bw(&vsi->back->hw, vsi->seid,
-                                      &bw_data, NULL);
-       if (ret) {
+       aq_ret = i40e_aq_config_vsi_tc_bw(&vsi->back->hw, vsi->seid, &bw_data,
+                                         NULL);
+       if (aq_ret) {
                dev_info(&vsi->back->pdev->dev,
                         "%s: AQ command Config VSI BW allocation per TC failed = %d\n",
                         __func__, vsi->back->hw.aq.asq_last_status);
-               return ret;
+               return -EINVAL;
        }
 
        for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
                vsi->info.qs_handle[i] = bw_data.qs_handles[i];
 
-       return ret;
+       return 0;
 }
 
 /**
index 79b58353d849177219f4e84e05bfabd64819d44a..47c2d10df8263422d8e23169939adc84a5f3012b 100644 (file)
@@ -719,6 +719,10 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw)
        u32 ctrl_ext;
        u32 mdic;
 
+       /* Extra read required for some PHY's on i354 */
+       if (hw->mac.type == e1000_i354)
+               igb_get_phy_id(hw);
+
        /* For SGMII PHYs, we try the list of possible addresses until
         * we find one that works.  For non-SGMII PHYs
         * (e.g. integrated copper PHYs), an address of 1 should
index f0dfd41dd4bdfff5aefff40c449fb4877f6797db..298f0ed50670c0388a53e82d3509beca6aaf351e 100644 (file)
@@ -712,6 +712,7 @@ static s32 igb_set_fc_watermarks(struct e1000_hw *hw)
 static s32 igb_set_default_fc(struct e1000_hw *hw)
 {
        s32 ret_val = 0;
+       u16 lan_offset;
        u16 nvm_data;
 
        /* Read and store word 0x0F of the EEPROM. This word contains bits
@@ -722,7 +723,14 @@ static s32 igb_set_default_fc(struct e1000_hw *hw)
         * control setting, then the variable hw->fc will
         * be initialized based on a value in the EEPROM.
         */
-       ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data);
+       if (hw->mac.type == e1000_i350) {
+               lan_offset = NVM_82580_LAN_FUNC_OFFSET(hw->bus.func);
+               ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG
+                                          + lan_offset, 1, &nvm_data);
+        } else {
+               ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG,
+                                          1, &nvm_data);
+        }
 
        if (ret_val) {
                hw_dbg("NVM Read Error\n");
index 48cbc833b051b3861a4568e72becf67eeaa357e4..86d51429a189295d9c7418a1273b625a933d9a9b 100644 (file)
@@ -1607,6 +1607,9 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter)
                        igb_write_phy_reg(hw, I347AT4_PAGE_SELECT, 0);
                        igb_write_phy_reg(hw, PHY_CONTROL, 0x4140);
                }
+       } else if (hw->phy.type == e1000_phy_82580) {
+               /* enable MII loopback */
+               igb_write_phy_reg(hw, I82580_PHY_LBK_CTRL, 0x8041);
        }
 
        /* add small delay to avoid loopback test failure */
index 8cf44f2a8ccd5b531f42fa0dfb357a19d6efa4f6..7579383c584db85954c872461fbd68037afbf8bb 100644 (file)
@@ -2034,21 +2034,15 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                return err;
 
        pci_using_dac = 0;
-       err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
+       err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
        if (!err) {
-               err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
-               if (!err)
-                       pci_using_dac = 1;
+               pci_using_dac = 1;
        } else {
-               err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+               err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
                if (err) {
-                       err = dma_set_coherent_mask(&pdev->dev,
-                                                   DMA_BIT_MASK(32));
-                       if (err) {
-                               dev_err(&pdev->dev,
-                                       "No usable DMA configuration, aborting\n");
-                               goto err_dma;
-                       }
+                       dev_err(&pdev->dev,
+                               "No usable DMA configuration, aborting\n");
+                       goto err_dma;
                }
        }
 
index 93eb7ee06d3e0aa2159fcccc61e797eb44fd79bd..4e6b02fbe65280614c68b6b76d013368281ccc4f 100644 (file)
@@ -2638,21 +2638,15 @@ static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                return err;
 
        pci_using_dac = 0;
-       err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
+       err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
        if (!err) {
-               err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
-               if (!err)
-                       pci_using_dac = 1;
+               pci_using_dac = 1;
        } else {
-               err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+               err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
                if (err) {
-                       err = dma_set_coherent_mask(&pdev->dev,
-                                                   DMA_BIT_MASK(32));
-                       if (err) {
-                               dev_err(&pdev->dev, "No usable DMA "
-                                       "configuration, aborting\n");
-                               goto err_dma;
-                       }
+                       dev_err(&pdev->dev, "No usable DMA "
+                               "configuration, aborting\n");
+                       goto err_dma;
                }
        }
 
index 9f6b236828e6a2d6e5342c0acfd5ba6222a4d531..57e390cbe6d0d21630f6bf6904a0c8a663601931 100644 (file)
@@ -408,20 +408,14 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                return err;
 
        pci_using_dac = 0;
-       err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
+       err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
        if (!err) {
-               err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
-               if (!err)
-                       pci_using_dac = 1;
+               pci_using_dac = 1;
        } else {
-               err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+               err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
                if (err) {
-                       err = dma_set_coherent_mask(&pdev->dev,
-                                                   DMA_BIT_MASK(32));
-                       if (err) {
-                               pr_err("No usable DMA configuration, aborting\n");
-                               goto err_dma_mask;
-                       }
+                       pr_err("No usable DMA configuration, aborting\n");
+                       goto err_dma_mask;
                }
        }
 
index 0e1b973659b0a006377fc2f4e84526266cdaecff..e8649abf97c0dd93152d7037bae870eaf3532954 100644 (file)
@@ -160,6 +160,13 @@ static int ixgbe_get_settings(struct net_device *netdev,
        bool autoneg = false;
        bool link_up;
 
+       /* SFP type is needed for get_link_capabilities */
+       if (hw->phy.media_type & (ixgbe_media_type_fiber |
+                                 ixgbe_media_type_fiber_qsfp)) {
+               if (hw->phy.sfp_type == ixgbe_sfp_type_not_present)
+                               hw->phy.ops.identify_sfp(hw);
+       }
+
        hw->mac.ops.get_link_capabilities(hw, &supported_link, &autoneg);
 
        /* set the supported link speeds */
@@ -186,6 +193,11 @@ static int ixgbe_get_settings(struct net_device *netdev,
                        ecmd->advertising |= ADVERTISED_1000baseT_Full;
                if (supported_link & IXGBE_LINK_SPEED_100_FULL)
                        ecmd->advertising |= ADVERTISED_100baseT_Full;
+
+               if (hw->phy.multispeed_fiber && !autoneg) {
+                       if (supported_link & IXGBE_LINK_SPEED_10GB_FULL)
+                               ecmd->advertising = ADVERTISED_10000baseT_Full;
+               }
        }
 
        if (autoneg) {
@@ -314,6 +326,14 @@ static int ixgbe_set_settings(struct net_device *netdev,
                if (ecmd->advertising & ~ecmd->supported)
                        return -EINVAL;
 
+               /* only allow one speed at a time if no autoneg */
+               if (!ecmd->autoneg && hw->phy.multispeed_fiber) {
+                       if (ecmd->advertising ==
+                           (ADVERTISED_10000baseT_Full |
+                            ADVERTISED_1000baseT_Full))
+                               return -EINVAL;
+               }
+
                old = hw->phy.autoneg_advertised;
                advertised = 0;
                if (ecmd->advertising & ADVERTISED_10000baseT_Full)
@@ -1805,6 +1825,10 @@ static int ixgbe_run_loopback_test(struct ixgbe_adapter *adapter)
        unsigned int size = 1024;
        netdev_tx_t tx_ret_val;
        struct sk_buff *skb;
+       u32 flags_orig = adapter->flags;
+
+       /* DCB can modify the frames on Tx */
+       adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
 
        /* allocate test skb */
        skb = alloc_skb(size, GFP_KERNEL);
@@ -1857,6 +1881,7 @@ static int ixgbe_run_loopback_test(struct ixgbe_adapter *adapter)
 
        /* free the original skb */
        kfree_skb(skb);
+       adapter->flags = flags_orig;
 
        return ret_val;
 }
index 7aba452833e5ef94ea1137f24729d36ddcf7d029..bf046e14ceb545313d777ba26d24edf4c785fe6f 100644 (file)
@@ -3571,7 +3571,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
        int i;
-       u32 rxctrl;
+       u32 rxctrl, rfctl;
 
        /* disable receives while setting up the descriptors */
        rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
@@ -3580,6 +3580,13 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
        ixgbe_setup_psrtype(adapter);
        ixgbe_setup_rdrxctl(adapter);
 
+       /* RSC Setup */
+       rfctl = IXGBE_READ_REG(hw, IXGBE_RFCTL);
+       rfctl &= ~IXGBE_RFCTL_RSC_DIS;
+       if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))
+               rfctl |= IXGBE_RFCTL_RSC_DIS;
+       IXGBE_WRITE_REG(hw, IXGBE_RFCTL, rfctl);
+
        /* Program registers for the distribution of queues */
        ixgbe_setup_mrqc(adapter);
 
@@ -5993,8 +6000,16 @@ static void ixgbe_sfp_link_config_subtask(struct ixgbe_adapter *adapter)
        adapter->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG;
 
        speed = hw->phy.autoneg_advertised;
-       if ((!speed) && (hw->mac.ops.get_link_capabilities))
+       if ((!speed) && (hw->mac.ops.get_link_capabilities)) {
                hw->mac.ops.get_link_capabilities(hw, &speed, &autoneg);
+
+               /* setup the highest link when no autoneg */
+               if (!autoneg) {
+                       if (speed & IXGBE_LINK_SPEED_10GB_FULL)
+                               speed = IXGBE_LINK_SPEED_10GB_FULL;
+               }
+       }
+
        if (hw->mac.ops.setup_link)
                hw->mac.ops.setup_link(hw, speed, true);
 
@@ -7475,19 +7490,14 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (err)
                return err;
 
-       if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) &&
-           !dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64))) {
+       if (!dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) {
                pci_using_dac = 1;
        } else {
-               err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+               err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
                if (err) {
-                       err = dma_set_coherent_mask(&pdev->dev,
-                                                   DMA_BIT_MASK(32));
-                       if (err) {
-                               dev_err(&pdev->dev,
-                                       "No usable DMA configuration, aborting\n");
-                               goto err_dma;
-                       }
+                       dev_err(&pdev->dev,
+                               "No usable DMA configuration, aborting\n");
+                       goto err_dma;
                }
                pci_using_dac = 0;
        }
index 6442cf8f9dceb4fc40d25aa5bcd0b3a97631e741..10775cb9b6d84c066263c51881257bf8995e037a 100644 (file)
@@ -1861,6 +1861,7 @@ enum {
 #define IXGBE_RFCTL_ISCSI_DIS       0x00000001
 #define IXGBE_RFCTL_ISCSI_DWC_MASK  0x0000003E
 #define IXGBE_RFCTL_ISCSI_DWC_SHIFT 1
+#define IXGBE_RFCTL_RSC_DIS            0x00000020
 #define IXGBE_RFCTL_NFSW_DIS        0x00000040
 #define IXGBE_RFCTL_NFSR_DIS        0x00000080
 #define IXGBE_RFCTL_NFS_VER_MASK    0x00000300
index 59a62bbfb3714a55683bec8fcb49e9adcb5cb279..e34c2daac6a0064303eff0c89ef9e9aeb225ff9a 100644 (file)
@@ -3326,19 +3326,14 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (err)
                return err;
 
-       if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) &&
-           !dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64))) {
+       if (!dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) {
                pci_using_dac = 1;
        } else {
-               err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+               err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
                if (err) {
-                       err = dma_set_coherent_mask(&pdev->dev,
-                                                   DMA_BIT_MASK(32));
-                       if (err) {
-                               dev_err(&pdev->dev, "No usable DMA "
-                                       "configuration, aborting\n");
-                               goto err_dma;
-                       }
+                       dev_err(&pdev->dev, "No usable DMA "
+                               "configuration, aborting\n");
+                       goto err_dma;
                }
                pci_using_dac = 0;
        }
index bfdb06860397e720a848d6e8cab7b324ded6ea1c..6a6c1f76d8e04406b1c6de12820a48a7d27337fd 100644 (file)
@@ -282,8 +282,7 @@ ltq_etop_hw_init(struct net_device *dev)
 
                if (IS_TX(i)) {
                        ltq_dma_alloc_tx(&ch->dma);
-                       request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
-                               "etop_tx", priv);
+                       request_irq(irq, ltq_etop_dma_irq, 0, "etop_tx", priv);
                } else if (IS_RX(i)) {
                        ltq_dma_alloc_rx(&ch->dma);
                        for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM;
@@ -291,8 +290,7 @@ ltq_etop_hw_init(struct net_device *dev)
                                if (ltq_etop_alloc_skb(ch))
                                        return -ENOMEM;
                        ch->dma.desc = 0;
-                       request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
-                               "etop_rx", priv);
+                       request_irq(irq, ltq_etop_dma_irq, 0, "etop_rx", priv);
                }
                ch->dma.irq = irq;
        }
index 4ae0c74260103fb65ffe58536d58ee3a3af9e6a2..fff62460185c3ea26572a4cf7c9aa2bfe28bfb72 100644 (file)
@@ -1123,8 +1123,7 @@ static int pxa168_eth_open(struct net_device *dev)
        struct pxa168_eth_private *pep = netdev_priv(dev);
        int err;
 
-       err = request_irq(dev->irq, pxa168_eth_int_handler,
-                         IRQF_DISABLED, dev->name, dev);
+       err = request_irq(dev->irq, pxa168_eth_int_handler, 0, dev->name, dev);
        if (err) {
                dev_err(&dev->dev, "can't assign irq\n");
                return -EAGAIN;
index ef94a591f9e550ed31d654c2cc1fa2ba7bc1bef9..ecc7f7b696b89a122b80318a12d5f6488a190126 100644 (file)
@@ -3086,23 +3086,27 @@ static struct sk_buff *skge_rx_get(struct net_device *dev,
                                               PCI_DMA_FROMDEVICE);
                skge_rx_reuse(e, skge->rx_buf_size);
        } else {
+               struct skge_element ee;
                struct sk_buff *nskb;
 
                nskb = netdev_alloc_skb_ip_align(dev, skge->rx_buf_size);
                if (!nskb)
                        goto resubmit;
 
+               ee = *e;
+
+               skb = ee.skb;
+               prefetch(skb->data);
+
                if (skge_rx_setup(skge, e, nskb, skge->rx_buf_size) < 0) {
                        dev_kfree_skb(nskb);
                        goto resubmit;
                }
 
                pci_unmap_single(skge->hw->pdev,
-                                dma_unmap_addr(e, mapaddr),
-                                dma_unmap_len(e, maplen),
+                                dma_unmap_addr(&ee, mapaddr),
+                                dma_unmap_len(&ee, maplen),
                                 PCI_DMA_FROMDEVICE);
-               skb = e->skb;
-               prefetch(skb->data);
        }
 
        skb_put(skb, len);
index a28cd801a236e5a674de67009a5b872ed29e9e71..0c750985f47e61f06bd402e390978800206b27f4 100644 (file)
@@ -53,9 +53,11 @@ static int mlx4_en_moderation_update(struct mlx4_en_priv *priv)
        for (i = 0; i < priv->tx_ring_num; i++) {
                priv->tx_cq[i].moder_cnt = priv->tx_frames;
                priv->tx_cq[i].moder_time = priv->tx_usecs;
-               err = mlx4_en_set_cq_moder(priv, &priv->tx_cq[i]);
-               if (err)
-                       return err;
+               if (priv->port_up) {
+                       err = mlx4_en_set_cq_moder(priv, &priv->tx_cq[i]);
+                       if (err)
+                               return err;
+               }
        }
 
        if (priv->adaptive_rx_coal)
@@ -65,9 +67,11 @@ static int mlx4_en_moderation_update(struct mlx4_en_priv *priv)
                priv->rx_cq[i].moder_cnt = priv->rx_frames;
                priv->rx_cq[i].moder_time = priv->rx_usecs;
                priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
-               err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]);
-               if (err)
-                       return err;
+               if (priv->port_up) {
+                       err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]);
+                       if (err)
+                               return err;
+               }
        }
 
        return err;
index 0fba1532d32646de3757896b101eec8ddba9889c..075f4e21d33df6f4f2b749dcd4aeb9fee1405077 100644 (file)
@@ -915,7 +915,7 @@ static int ks_net_open(struct net_device *netdev)
        struct ks_net *ks = netdev_priv(netdev);
        int err;
 
-#define        KS_INT_FLAGS    (IRQF_DISABLED|IRQF_TRIGGER_LOW)
+#define        KS_INT_FLAGS    IRQF_TRIGGER_LOW
        /* lock the card, even if we may not actually do anything
         * else at the moment.
         */
index 83c2091c9c234bfe9ecbb4067d1396aee19f49f6..bd1a2d2bc2aebbad9612d167915fd743cf973c94 100644 (file)
@@ -543,7 +543,7 @@ static const struct of_device_id moxart_mac_match[] = {
        { }
 };
 
-struct __initdata platform_driver moxart_mac_driver = {
+static struct platform_driver moxart_mac_driver = {
        .probe  = moxart_mac_probe,
        .remove = moxart_remove,
        .driver = {
index c20766c2f65b91c57de2ba68ccb4d98058544059..79257f71c5d95e9daac062f111dd1ac3792885d8 100644 (file)
@@ -83,8 +83,7 @@ static int jazzsonic_open(struct net_device* dev)
 {
        int retval;
 
-       retval = request_irq(dev->irq, sonic_interrupt, IRQF_DISABLED,
-                               "sonic", dev);
+       retval = request_irq(dev->irq, sonic_interrupt, 0, "sonic", dev);
        if (retval) {
                printk(KERN_ERR "%s: unable to get IRQ %d.\n",
                                dev->name, dev->irq);
index c2e0256fe3dfb423d1ba9011d7035379e1dd3f47..4da172ac55991bd69b50037501c3fc886728dc08 100644 (file)
@@ -95,8 +95,7 @@ static int xtsonic_open(struct net_device *dev)
 {
        int retval;
 
-       retval = request_irq(dev->irq, sonic_interrupt, IRQF_DISABLED,
-                               "sonic", dev);
+       retval = request_irq(dev->irq, sonic_interrupt, 0, "sonic", dev);
        if (retval) {
                printk(KERN_ERR "%s: unable to get IRQ %d.\n",
                       dev->name, dev->irq);
index a061b93efe66a29fd663a49bf16d1a510ff0879f..ba3ca18611f7905d559eaec225b6a4ae837c3dda 100644 (file)
@@ -1399,8 +1399,10 @@ static int lpc_eth_drv_probe(struct platform_device *pdev)
        }
 
        if (pldat->dma_buff_base_v == 0) {
-               pldat->pdev->dev.coherent_dma_mask = 0xFFFFFFFF;
-               pldat->pdev->dev.dma_mask = &pldat->pdev->dev.coherent_dma_mask;
+               ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+               if (ret)
+                       goto err_out_free_irq;
+
                pldat->dma_buff_size = PAGE_ALIGN(pldat->dma_buff_size);
 
                /* Allocate a chunk of memory for the DMA ethernet buffers
index 622aa75904c4ee07c1b666466925e08ce0df25d3..2006a07004829dcc7f1743cf343480c6db3c5c95 100644 (file)
@@ -1552,8 +1552,9 @@ static int octeon_mgmt_probe(struct platform_device *pdev)
 
        p->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
 
-       pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64);
-       pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+       result = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+       if (result)
+               goto err;
 
        netif_carrier_off(netdev);
        result = register_netdev(netdev);
index c498181a9aa823e18e9e120821254c3721bbdad3..5b65356e7568b28e0d2030c7436863db10a44b32 100644 (file)
@@ -1219,7 +1219,7 @@ static int pasemi_mac_open(struct net_device *dev)
        snprintf(mac->tx_irq_name, sizeof(mac->tx_irq_name), "%s tx",
                 dev->name);
 
-       ret = request_irq(mac->tx->chan.irq, pasemi_mac_tx_intr, IRQF_DISABLED,
+       ret = request_irq(mac->tx->chan.irq, pasemi_mac_tx_intr, 0,
                          mac->tx_irq_name, mac->tx);
        if (ret) {
                dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n",
@@ -1230,7 +1230,7 @@ static int pasemi_mac_open(struct net_device *dev)
        snprintf(mac->rx_irq_name, sizeof(mac->rx_irq_name), "%s rx",
                 dev->name);
 
-       ret = request_irq(mac->rx->chan.irq, pasemi_mac_rx_intr, IRQF_DISABLED,
+       ret = request_irq(mac->rx->chan.irq, pasemi_mac_rx_intr, 0,
                          mac->rx_irq_name, mac->rx);
        if (ret) {
                dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n",
index 4d7ad0074d1c0c1eb1ef1026ab8954bd050f4071..ebe4c86e5230223f0c5465485a9812dc1a0aa3b0 100644 (file)
@@ -1794,3 +1794,11 @@ const struct ethtool_ops qlcnic_sriov_vf_ethtool_ops = {
        .set_msglevel           = qlcnic_set_msglevel,
        .get_msglevel           = qlcnic_get_msglevel,
 };
+
+const struct ethtool_ops qlcnic_ethtool_failed_ops = {
+       .get_settings           = qlcnic_get_settings,
+       .get_drvinfo            = qlcnic_get_drvinfo,
+       .set_msglevel           = qlcnic_set_msglevel,
+       .get_msglevel           = qlcnic_get_msglevel,
+       .set_dump               = qlcnic_set_dump,
+};
index c4c5023e1fdf64aed12efce219e2acb04922b142..21d00a0449a10f394fe6b02d5689c7b0ab3b95cf 100644 (file)
@@ -431,6 +431,9 @@ static void qlcnic_82xx_cancel_idc_work(struct qlcnic_adapter *adapter)
        while (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
                usleep_range(10000, 11000);
 
+       if (!adapter->fw_work.work.func)
+               return;
+
        cancel_delayed_work_sync(&adapter->fw_work);
 }
 
@@ -2275,8 +2278,9 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                adapter->portnum = adapter->ahw->pci_func;
                err = qlcnic_start_firmware(adapter);
                if (err) {
-                       dev_err(&pdev->dev, "Loading fw failed.Please Reboot\n");
-                       goto err_out_free_hw;
+                       dev_err(&pdev->dev, "Loading fw failed.Please Reboot\n"
+                               "\t\tIf reboot doesn't help, try flashing the card\n");
+                       goto err_out_maintenance_mode;
                }
 
                qlcnic_get_multiq_capability(adapter);
@@ -2408,6 +2412,22 @@ err_out_disable_pdev:
        pci_set_drvdata(pdev, NULL);
        pci_disable_device(pdev);
        return err;
+
+err_out_maintenance_mode:
+       netdev->netdev_ops = &qlcnic_netdev_failed_ops;
+       SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_failed_ops);
+       err = register_netdev(netdev);
+
+       if (err) {
+               dev_err(&pdev->dev, "Failed to register net device\n");
+               qlcnic_clr_all_drv_state(adapter, 0);
+               goto err_out_free_hw;
+       }
+
+       pci_set_drvdata(pdev, adapter);
+       qlcnic_add_sysfs(adapter);
+
+       return 0;
 }
 
 static void qlcnic_remove(struct pci_dev *pdev)
@@ -2518,8 +2538,16 @@ static int qlcnic_resume(struct pci_dev *pdev)
 static int qlcnic_open(struct net_device *netdev)
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
+       u32 state;
        int err;
 
+       state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
+       if (state == QLCNIC_DEV_FAILED || state == QLCNIC_DEV_BADBAD) {
+               netdev_err(netdev, "%s: Device is in FAILED state\n", __func__);
+
+               return -EIO;
+       }
+
        netif_carrier_off(netdev);
 
        err = qlcnic_attach(adapter);
@@ -3228,6 +3256,13 @@ void qlcnic_82xx_dev_request_reset(struct qlcnic_adapter *adapter, u32 key)
                return;
 
        state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
+       if (state == QLCNIC_DEV_FAILED || state == QLCNIC_DEV_BADBAD) {
+               netdev_err(adapter->netdev, "%s: Device is in FAILED state\n",
+                          __func__);
+               qlcnic_api_unlock(adapter);
+
+               return;
+       }
 
        if (state == QLCNIC_DEV_READY) {
                QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE,
index 652cc13c5023ccfca09bed0978b166914e97a9a8..392b9bd12b4fb67585501f817defd1fb0194b9ca 100644 (file)
@@ -1561,6 +1561,7 @@ static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter)
 {
        int err;
 
+       adapter->need_fw_reset = 0;
        qlcnic_83xx_reinit_mbx_work(adapter->ahw->mailbox);
        qlcnic_83xx_enable_mbx_interrupt(adapter);
 
index 330d9a8774ad69a1d6d8e4d4f38aa87e243bf699..686f460b15022b4b2b7759ad29493a64a1f84592 100644 (file)
@@ -397,6 +397,7 @@ static int qlcnic_pci_sriov_disable(struct qlcnic_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
 
+       rtnl_lock();
        if (netif_running(netdev))
                __qlcnic_down(adapter, netdev);
 
@@ -407,12 +408,15 @@ static int qlcnic_pci_sriov_disable(struct qlcnic_adapter *adapter)
        /* After disabling SRIOV re-init the driver in default mode
           configure opmode based on op_mode of function
         */
-       if (qlcnic_83xx_configure_opmode(adapter))
+       if (qlcnic_83xx_configure_opmode(adapter)) {
+               rtnl_unlock();
                return -EIO;
+       }
 
        if (netif_running(netdev))
                __qlcnic_up(adapter, netdev);
 
+       rtnl_unlock();
        return 0;
 }
 
@@ -533,6 +537,7 @@ static int qlcnic_pci_sriov_enable(struct qlcnic_adapter *adapter, int num_vfs)
                return -EIO;
        }
 
+       rtnl_lock();
        if (netif_running(netdev))
                __qlcnic_down(adapter, netdev);
 
@@ -555,6 +560,7 @@ static int qlcnic_pci_sriov_enable(struct qlcnic_adapter *adapter, int num_vfs)
                __qlcnic_up(adapter, netdev);
 
 error:
+       rtnl_unlock();
        return err;
 }
 
index c6165d05cc13c3806cf60d9ac7513ffdf5832eed..019f4377307f025df8d7f93d3e473e7811f4101a 100644 (file)
@@ -1272,6 +1272,7 @@ void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter)
 void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
 {
        struct device *dev = &adapter->pdev->dev;
+       u32 state;
 
        if (device_create_bin_file(dev, &bin_attr_port_stats))
                dev_info(dev, "failed to create port stats sysfs entry");
@@ -1285,8 +1286,13 @@ void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
        if (device_create_bin_file(dev, &bin_attr_mem))
                dev_info(dev, "failed to create mem sysfs entry\n");
 
+       state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
+       if (state == QLCNIC_DEV_FAILED || state == QLCNIC_DEV_BADBAD)
+               return;
+
        if (device_create_bin_file(dev, &bin_attr_pci_config))
                dev_info(dev, "failed to create pci config sysfs entry");
+
        if (device_create_file(dev, &dev_attr_beacon))
                dev_info(dev, "failed to create beacon sysfs entry");
 
@@ -1307,6 +1313,7 @@ void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
 void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
 {
        struct device *dev = &adapter->pdev->dev;
+       u32 state;
 
        device_remove_bin_file(dev, &bin_attr_port_stats);
 
@@ -1315,6 +1322,11 @@ void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
        device_remove_file(dev, &dev_attr_diag_mode);
        device_remove_bin_file(dev, &bin_attr_crb);
        device_remove_bin_file(dev, &bin_attr_mem);
+
+       state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
+       if (state == QLCNIC_DEV_FAILED || state == QLCNIC_DEV_BADBAD)
+               return;
+
        device_remove_bin_file(dev, &bin_attr_pci_config);
        device_remove_file(dev, &dev_attr_beacon);
        if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
index 10093f0c4c0f3d507514da946df9047b3d68d925..6bc5db7039201a1af0a835867e900ed59ab0af13 100644 (file)
@@ -740,8 +740,8 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
        int i;
 
        if (!mpi_coredump) {
-               netif_err(qdev, drv, qdev->ndev, "No memory available\n");
-               return -ENOMEM;
+               netif_err(qdev, drv, qdev->ndev, "No memory allocated\n");
+               return -EINVAL;
        }
 
        /* Try to get the spinlock, but dont worry if
index ff2bf8a4e24773429f02e1b66777e76bdd079134..7ad146080c3649585e5c4611c6ba79883bda6293 100644 (file)
@@ -1274,7 +1274,7 @@ void ql_mpi_reset_work(struct work_struct *work)
                return;
        }
 
-       if (!ql_core_dump(qdev, qdev->mpi_coredump)) {
+       if (qdev->mpi_coredump && !ql_core_dump(qdev, qdev->mpi_coredump)) {
                netif_err(qdev, drv, qdev->ndev, "Core is dumped!\n");
                qdev->core_is_dumped = 1;
                queue_delayed_work(qdev->workqueue,
index 6f87f2cde647fba98bed02cc599afff911125ded..3397cee89777ba4be6c888fe9711e928ef209e06 100644 (file)
@@ -4231,6 +4231,7 @@ static void rtl_init_rxcfg(struct rtl8169_private *tp)
        case RTL_GIGA_MAC_VER_23:
        case RTL_GIGA_MAC_VER_24:
        case RTL_GIGA_MAC_VER_34:
+       case RTL_GIGA_MAC_VER_35:
                RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
                break;
        case RTL_GIGA_MAC_VER_40:
index 8b7152565c5e27bed528dc7ea5b2e104efd3abb1..0889212944486f9978c2c9f404bd3c87b4b5777f 100644 (file)
@@ -7,7 +7,7 @@ config SFC
        select I2C_ALGOBIT
        select PTP_1588_CLOCK
        ---help---
-         This driver supports 10-gigabit Ethernet cards based on
+         This driver supports 10/40-gigabit Ethernet cards based on
          the Solarflare SFC4000, SFC9000-family and SFC9100-family
          controllers.
 
index 5f42313b4965a3013f5e28c907895783aa5206cb..9f18ae984f9ed38386b16e5284d4d10864687c4b 100644 (file)
@@ -94,7 +94,7 @@ static unsigned int efx_ef10_mem_map_size(struct efx_nic *efx)
        return resource_size(&efx->pci_dev->resource[EFX_MEM_BAR]);
 }
 
-static int efx_ef10_init_capabilities(struct efx_nic *efx)
+static int efx_ef10_init_datapath_caps(struct efx_nic *efx)
 {
        MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CAPABILITIES_OUT_LEN);
        struct efx_ef10_nic_data *nic_data = efx->nic_data;
@@ -107,16 +107,27 @@ static int efx_ef10_init_capabilities(struct efx_nic *efx)
                          outbuf, sizeof(outbuf), &outlen);
        if (rc)
                return rc;
+       if (outlen < sizeof(outbuf)) {
+               netif_err(efx, drv, efx->net_dev,
+                         "unable to read datapath firmware capabilities\n");
+               return -EIO;
+       }
 
-       if (outlen >= sizeof(outbuf)) {
-               nic_data->datapath_caps =
-                       MCDI_DWORD(outbuf, GET_CAPABILITIES_OUT_FLAGS1);
-               if (!(nic_data->datapath_caps &
-                    (1 << MC_CMD_GET_CAPABILITIES_OUT_TX_TSO_LBN))) {
-                       netif_err(efx, drv, efx->net_dev,
-                                 "Capabilities don't indicate TSO support.\n");
-                       return -ENODEV;
-               }
+       nic_data->datapath_caps =
+               MCDI_DWORD(outbuf, GET_CAPABILITIES_OUT_FLAGS1);
+
+       if (!(nic_data->datapath_caps &
+             (1 << MC_CMD_GET_CAPABILITIES_OUT_TX_TSO_LBN))) {
+               netif_err(efx, drv, efx->net_dev,
+                         "current firmware does not support TSO\n");
+               return -ENODEV;
+       }
+
+       if (!(nic_data->datapath_caps &
+             (1 << MC_CMD_GET_CAPABILITIES_OUT_RX_PREFIX_LEN_14_LBN))) {
+               netif_err(efx, probe, efx->net_dev,
+                         "current firmware does not support an RX prefix\n");
+               return -ENODEV;
        }
 
        return 0;
@@ -217,21 +228,13 @@ static int efx_ef10_probe(struct efx_nic *efx)
        if (rc)
                goto fail3;
 
-       rc = efx_ef10_init_capabilities(efx);
+       rc = efx_ef10_init_datapath_caps(efx);
        if (rc < 0)
                goto fail3;
 
        efx->rx_packet_len_offset =
                ES_DZ_RX_PREFIX_PKTLEN_OFST - ES_DZ_RX_PREFIX_SIZE;
 
-       if (!(nic_data->datapath_caps &
-             (1 << MC_CMD_GET_CAPABILITIES_OUT_RX_PREFIX_LEN_14_LBN))) {
-               netif_err(efx, probe, efx->net_dev,
-                         "current firmware does not support an RX prefix\n");
-               rc = -ENODEV;
-               goto fail3;
-       }
-
        rc = efx_mcdi_port_get_number(efx);
        if (rc < 0)
                goto fail3;
@@ -260,8 +263,6 @@ static int efx_ef10_probe(struct efx_nic *efx)
        if (rc)
                goto fail3;
 
-       efx_ptp_probe(efx);
-
        return 0;
 
 fail3:
@@ -342,6 +343,13 @@ static int efx_ef10_init_nic(struct efx_nic *efx)
        struct efx_ef10_nic_data *nic_data = efx->nic_data;
        int rc;
 
+       if (nic_data->must_check_datapath_caps) {
+               rc = efx_ef10_init_datapath_caps(efx);
+               if (rc)
+                       return rc;
+               nic_data->must_check_datapath_caps = false;
+       }
+
        if (nic_data->must_realloc_vis) {
                /* We cannot let the number of VIs change now */
                rc = efx_ef10_alloc_vis(efx, nic_data->n_allocated_vis,
@@ -710,6 +718,14 @@ static int efx_ef10_mcdi_poll_reboot(struct efx_nic *efx)
        nic_data->must_restore_filters = true;
        nic_data->rx_rss_context = EFX_EF10_RSS_CONTEXT_INVALID;
 
+       /* The datapath firmware might have been changed */
+       nic_data->must_check_datapath_caps = true;
+
+       /* MAC statistics have been cleared on the NIC; clear the local
+        * statistic that we update with efx_update_diff_stat().
+        */
+       nic_data->stats[EF10_STAT_rx_bad_bytes] = 0;
+
        return -EIO;
 }
 
index 07c9bc4c61bc0d15484e79798b36720eff8ff741..2e27837ce6a289dc033c806e613f8dbca42496b9 100644 (file)
@@ -1121,7 +1121,7 @@ static int efx_init_io(struct efx_nic *efx)
         */
        while (dma_mask > 0x7fffffffUL) {
                if (dma_supported(&pci_dev->dev, dma_mask)) {
-                       rc = dma_set_mask(&pci_dev->dev, dma_mask);
+                       rc = dma_set_mask_and_coherent(&pci_dev->dev, dma_mask);
                        if (rc == 0)
                                break;
                }
@@ -1134,16 +1134,6 @@ static int efx_init_io(struct efx_nic *efx)
        }
        netif_dbg(efx, probe, efx->net_dev,
                  "using DMA mask %llx\n", (unsigned long long) dma_mask);
-       rc = dma_set_coherent_mask(&pci_dev->dev, dma_mask);
-       if (rc) {
-               /* dma_set_coherent_mask() is not *allowed* to
-                * fail with a mask that dma_set_mask() accepted,
-                * but just in case...
-                */
-               netif_err(efx, probe, efx->net_dev,
-                         "failed to set consistent DMA mask\n");
-               goto fail2;
-       }
 
        efx->membase_phys = pci_resource_start(efx->pci_dev, EFX_MEM_BAR);
        rc = pci_request_region(pci_dev, EFX_MEM_BAR, "sfc");
index 128d7cdf9eb207583afc36dc8706ef3503b3f5a5..c082562dbf4ee8d96388dc21e0b2da1803fe84f2 100644 (file)
 
 /* A reboot/assertion causes the MCDI status word to be set after the
  * command word is set or a REBOOT event is sent. If we notice a reboot
- * via these mechanisms then wait 20ms for the status word to be set.
+ * via these mechanisms then wait 250ms for the status word to be set.
  */
 #define MCDI_STATUS_DELAY_US           100
-#define MCDI_STATUS_DELAY_COUNT                200
+#define MCDI_STATUS_DELAY_COUNT                2500
 #define MCDI_STATUS_SLEEP_MS                                           \
        (MCDI_STATUS_DELAY_US * MCDI_STATUS_DELAY_COUNT / 1000)
 
@@ -800,9 +800,6 @@ static void efx_mcdi_ev_death(struct efx_nic *efx, int rc)
        } else {
                int count;
 
-               /* Nobody was waiting for an MCDI request, so trigger a reset */
-               efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
-
                /* Consume the status word since efx_mcdi_rpc_finish() won't */
                for (count = 0; count < MCDI_STATUS_DELAY_COUNT; ++count) {
                        if (efx_mcdi_poll_reboot(efx))
@@ -810,6 +807,9 @@ static void efx_mcdi_ev_death(struct efx_nic *efx, int rc)
                        udelay(MCDI_STATUS_DELAY_US);
                }
                mcdi->new_epoch = true;
+
+               /* Nobody was waiting for an MCDI request, so trigger a reset */
+               efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
        }
 
        spin_unlock(&mcdi->iface_lock);
index 8d33da6697fbef6fefa40955d8fb01231b3c9c79..7b6be61d549fd57f81d1d7a31b6ef374d0f5acfb 100644 (file)
@@ -556,6 +556,7 @@ static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ec
                case 100:   caps = 1 << MC_CMD_PHY_CAP_100FDX_LBN;   break;
                case 1000:  caps = 1 << MC_CMD_PHY_CAP_1000FDX_LBN;  break;
                case 10000: caps = 1 << MC_CMD_PHY_CAP_10000FDX_LBN; break;
+               case 40000: caps = 1 << MC_CMD_PHY_CAP_40000FDX_LBN; break;
                default:    return -EINVAL;
                }
        } else {
@@ -841,6 +842,7 @@ static unsigned int efx_mcdi_event_link_speed[] = {
        [MCDI_EVENT_LINKCHANGE_SPEED_100M] = 100,
        [MCDI_EVENT_LINKCHANGE_SPEED_1G] = 1000,
        [MCDI_EVENT_LINKCHANGE_SPEED_10G] = 10000,
+       [MCDI_EVENT_LINKCHANGE_SPEED_40G] = 40000,
 };
 
 void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev)
index 4b1e188f7a2fc51a640bc03f79752428867ad33b..fda29d39032f422d2c395a4fe68a4c5091654006 100644 (file)
@@ -400,6 +400,8 @@ enum {
  * @rx_rss_context: Firmware handle for our RSS context
  * @stats: Hardware statistics
  * @workaround_35388: Flag: firmware supports workaround for bug 35388
+ * @must_check_datapath_caps: Flag: @datapath_caps needs to be revalidated
+ *     after MC reboot
  * @datapath_caps: Capabilities of datapath firmware (FLAGS1 field of
  *     %MC_CMD_GET_CAPABILITIES response)
  */
@@ -413,6 +415,7 @@ struct efx_ef10_nic_data {
        u32 rx_rss_context;
        u64 stats[EF10_STAT_COUNT];
        bool workaround_35388;
+       bool must_check_datapath_caps;
        u32 datapath_caps;
 };
 
index 370e13dde115a31a1bd4feba15d1c264b8fcdbef..5730fe2445a6c1acf5dfa5cd8767d1b1bb749734 100644 (file)
@@ -271,7 +271,7 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l)
 #define SMC_insw(a, r, p, l)   mcf_insw(a + r, p, l)
 #define SMC_outsw(a, r, p, l)  mcf_outsw(a + r, p, l)
 
-#define SMC_IRQ_FLAGS          (IRQF_DISABLED)
+#define SMC_IRQ_FLAGS          0
 
 #else
 
index ffa5c4ad12105a2050d264d4deac90080f7e4c9d..5f9e79f7f2df52f8b6a3c1955bd7e99ba4bbb122 100644 (file)
@@ -1356,8 +1356,7 @@ static int smsc9420_open(struct net_device *dev)
        smsc9420_reg_write(pd, INT_STAT, 0xFFFFFFFF);
        smsc9420_pci_flush_write(pd);
 
-       result = request_irq(irq, smsc9420_isr, IRQF_SHARED | IRQF_DISABLED,
-                            DRV_NAME, pd);
+       result = request_irq(irq, smsc9420_isr, IRQF_SHARED, DRV_NAME, pd);
        if (result) {
                smsc_warn(IFUP, "Unable to use IRQ = %d", irq);
                result = -ENODEV;
index 9c805e0c0cae87bd81bb305a6c51cb3c58b479e1..f7f2ef49c0c1cbbe4756c805797bedb71cc6495f 100644 (file)
@@ -1726,7 +1726,7 @@ static int ps3_gelic_driver_probe(struct ps3_system_bus_device *dev)
                goto fail_alloc_irq;
        }
        result = request_irq(card->irq, gelic_card_interrupt,
-                            IRQF_DISABLED, netdev->name, card);
+                            0, netdev->name, card);
 
        if (result) {
                dev_info(ctodev(card), "%s:request_irq failed (%d)\n",
index c8f088ab5fdfdbb6c9c757f5defd9c9b70588163..bdf697b184ae14246a4173d09833367ba312d7df 100644 (file)
@@ -32,7 +32,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #define DRV_NAME       "via-rhine"
-#define DRV_VERSION    "1.5.0"
+#define DRV_VERSION    "1.5.1"
 #define DRV_RELDATE    "2010-10-09"
 
 #include <linux/types.h>
@@ -1704,7 +1704,12 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb,
                cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
 
        if (unlikely(vlan_tx_tag_present(skb))) {
-               rp->tx_ring[entry].tx_status = cpu_to_le32((vlan_tx_tag_get(skb)) << 16);
+               u16 vid_pcp = vlan_tx_tag_get(skb);
+
+               /* drop CFI/DEI bit, register needs VID and PCP */
+               vid_pcp = (vid_pcp & VLAN_VID_MASK) |
+                         ((vid_pcp & VLAN_PRIO_MASK) >> 1);
+               rp->tx_ring[entry].tx_status = cpu_to_le32((vid_pcp) << 16);
                /* request tagging */
                rp->tx_ring[entry].desc_length |= cpu_to_le32(0x020000);
        }
index b88121f240ca609ea26f911508b829c8fbbdbdd1..0029148077a9805a288a42a9d8207a97ce6e8133 100644 (file)
@@ -297,6 +297,12 @@ static int temac_dma_bd_init(struct net_device *ndev)
                       lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1)));
        lp->dma_out(lp, TX_CURDESC_PTR, lp->tx_bd_p);
 
+       /* Init descriptor indexes */
+       lp->tx_bd_ci = 0;
+       lp->tx_bd_next = 0;
+       lp->tx_bd_tail = 0;
+       lp->rx_bd_ci = 0;
+
        return 0;
 
 out:
index f07c340990da570303a25a0e44cbf7ca4b21efa8..3f138ca88670ce608731cdcd4d636bc87d3a2cac 100644 (file)
@@ -191,8 +191,8 @@ static inline int mcs_setup_transceiver_vishay(struct mcs_cb *mcs)
                goto error;
 
        ret = 0;
-       error:
-               return ret;
+error:
+       return ret;
 }
 
 /* Setup a communication between mcs7780 and agilent chip. */
@@ -501,8 +501,11 @@ static inline int mcs_setup_urbs(struct mcs_cb *mcs)
                return 0;
 
        mcs->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!mcs->rx_urb)
+       if (!mcs->rx_urb) {
+               usb_free_urb(mcs->tx_urb);
+               mcs->tx_urb = NULL;
                return 0;
+       }
 
        return 1;
 }
@@ -643,9 +646,9 @@ static int mcs_speed_change(struct mcs_cb *mcs)
        ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
 
        mcs->speed = mcs->new_speed;
-       error:
-               mcs->new_speed = 0;
-               return ret;
+error:
+       mcs->new_speed = 0;
+       return ret;
 }
 
 /* Ioctl calls not supported at this time.  Can be an area of future work. */
@@ -738,17 +741,20 @@ static int mcs_net_open(struct net_device *netdev)
 
        ret = mcs_receive_start(mcs);
        if (ret)
-               goto error3;
+               goto error4;
 
        netif_start_queue(netdev);
        return 0;
 
-       error3:
-               irlap_close(mcs->irlap);
-       error2:
-               kfree_skb(mcs->rx_buff.skb);
-       error1:
-               return ret;
+error4:
+       usb_free_urb(mcs->rx_urb);
+       usb_free_urb(mcs->tx_urb);
+error3:
+       irlap_close(mcs->irlap);
+error2:
+       kfree_skb(mcs->rx_buff.skb);
+error1:
+       return ret;
 }
 
 /* Receive callback function.  */
@@ -946,11 +952,11 @@ static int mcs_probe(struct usb_interface *intf,
        usb_set_intfdata(intf, mcs);
        return 0;
 
-       error2:
-               free_netdev(ndev);
+error2:
+       free_netdev(ndev);
 
-       error1:
-               return ret;
+error1:
+       return ret;
 }
 
 /* The current device is removed, the USB layer tells us to shut down. */
index fcbf680c3e62f73af4933896641045de34f1f68c..a17d85a331f1ade54f9ec1834f1e8ee1c67d9b9d 100644 (file)
@@ -146,6 +146,7 @@ static int loopback_dev_init(struct net_device *dev)
 
 static void loopback_dev_free(struct net_device *dev)
 {
+       dev_net(dev)->loopback_dev = NULL;
        free_percpu(dev->lstats);
        free_netdev(dev);
 }
index dcb21347c67044da535903f2f88ba36f2529f347..adeee615dd19f4e0d7c6288466798781a1f8bda7 100644 (file)
@@ -684,15 +684,12 @@ restart:
                        case NETDEV_RELEASE:
                        case NETDEV_JOIN:
                        case NETDEV_UNREGISTER:
-                               /*
-                                * rtnl_lock already held
+                               /* rtnl_lock already held
                                 * we might sleep in __netpoll_cleanup()
                                 */
                                spin_unlock_irqrestore(&target_list_lock, flags);
 
-                               mutex_lock(&nt->mutex);
                                __netpoll_cleanup(&nt->np);
-                               mutex_unlock(&nt->mutex);
 
                                spin_lock_irqsave(&target_list_lock, flags);
                                dev_put(nt->np.dev);
index db472ffb6e89ed269f11e09fc032c8b9a714f03c..313a0377f68fc98f244ab145c7823ce3bf9ddaed 100644 (file)
@@ -30,9 +30,9 @@
 #include <linux/ethtool.h>
 #include <linux/phy.h>
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /* Cicada Extended Control Register 1 */
 #define MII_CIS8201_EXT_CON1           0x17
index 6fa5ae00039fd65b2c634d0d22241d9c7a9d13e2..01805319e1e0335a70f86109e058cac44d669ee0 100644 (file)
@@ -281,7 +281,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
        nf_reset(skb);
 
        skb->ip_summed = CHECKSUM_NONE;
-       ip_select_ident(iph, &rt->dst, NULL);
+       ip_select_ident(skb, &rt->dst, NULL);
        ip_send_check(iph);
 
        ip_local_out(skb);
index a34d6bf5e43b5b29325215e358cca9ee3fc734ee..cc70ecfc70626789183e462c8b51d13f0c7fc8aa 100644 (file)
@@ -429,11 +429,13 @@ static void slip_write_wakeup(struct tty_struct *tty)
        if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev))
                return;
 
+       spin_lock(&sl->lock);
        if (sl->xleft <= 0)  {
                /* Now serial buffer is almost free & we can start
                 * transmission of another packet */
                sl->dev->stats.tx_packets++;
                clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+               spin_unlock(&sl->lock);
                sl_unlock(sl);
                return;
        }
@@ -441,6 +443,7 @@ static void slip_write_wakeup(struct tty_struct *tty)
        actual = tty->ops->write(tty, sl->xhead, sl->xleft);
        sl->xleft -= actual;
        sl->xhead += actual;
+       spin_unlock(&sl->lock);
 }
 
 static void sl_tx_timeout(struct net_device *dev)
index a639de8401f8741ce7325b5261fe9c42ee377be7..807815fc996839d14efd18625fb300a2f48d2577 100644 (file)
@@ -1641,11 +1641,11 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
                INIT_LIST_HEAD(&tun->disabled);
                err = tun_attach(tun, file, false);
                if (err < 0)
-                       goto err_free_dev;
+                       goto err_free_flow;
 
                err = register_netdevice(tun->dev);
                if (err < 0)
-                       goto err_free_dev;
+                       goto err_detach;
 
                if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) ||
                    device_create_file(&tun->dev->dev, &dev_attr_owner) ||
@@ -1689,7 +1689,12 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
        strcpy(ifr->ifr_name, tun->dev->name);
        return 0;
 
- err_free_dev:
+err_detach:
+       tun_detach_all(dev);
+err_free_flow:
+       tun_flow_uninit(tun);
+       security_tun_dev_free_security(tun->security);
+err_free_dev:
        free_netdev(dev);
        return err;
 }
index 03ad4dc293aa2a468f8a93f0a0d045623507a9a0..2023f3ea891e6bf75f0c62d3d78213e30d1a11f4 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/usb/usbnet.h>
 
 
-#if defined(CONFIG_USB_NET_RNDIS_HOST) || defined(CONFIG_USB_NET_RNDIS_HOST_MODULE)
+#if IS_ENABLED(CONFIG_USB_NET_RNDIS_HOST)
 
 static int is_rndis(struct usb_interface_descriptor *desc)
 {
@@ -69,8 +69,7 @@ static const u8 mbm_guid[16] = {
        0xa6, 0x07, 0xc0, 0xff, 0xcb, 0x7e, 0x39, 0x2a,
 };
 
-/*
- * probes control interface, claims data interface, collects the bulk
+/* probes control interface, claims data interface, collects the bulk
  * endpoints, activates data interface (if needed), maybe sets MTU.
  * all pure cdc, except for certain firmware workarounds, and knowing
  * that rndis uses one different rule.
@@ -88,7 +87,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
        struct usb_cdc_mdlm_desc        *desc = NULL;
        struct usb_cdc_mdlm_detail_desc *detail = NULL;
 
-       if (sizeof dev->data < sizeof *info)
+       if (sizeof(dev->data) < sizeof(*info))
                return -EDOM;
 
        /* expect strict spec conformance for the descriptors, but
@@ -126,10 +125,10 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
                 is_activesync(&intf->cur_altsetting->desc) ||
                 is_wireless_rndis(&intf->cur_altsetting->desc));
 
-       memset(info, 0, sizeof *info);
+       memset(info, 0, sizeof(*info));
        info->control = intf;
        while (len > 3) {
-               if (buf [1] != USB_DT_CS_INTERFACE)
+               if (buf[1] != USB_DT_CS_INTERFACE)
                        goto next_desc;
 
                /* use bDescriptorSubType to identify the CDC descriptors.
@@ -139,14 +138,14 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
                 * in favor of a complicated OID-based RPC scheme doing what
                 * CDC Ethernet achieves with a simple descriptor.
                 */
-               switch (buf [2]) {
+               switch (buf[2]) {
                case USB_CDC_HEADER_TYPE:
                        if (info->header) {
                                dev_dbg(&intf->dev, "extra CDC header\n");
                                goto bad_desc;
                        }
                        info->header = (void *) buf;
-                       if (info->header->bLength != sizeof *info->header) {
+                       if (info->header->bLength != sizeof(*info->header)) {
                                dev_dbg(&intf->dev, "CDC header len %u\n",
                                        info->header->bLength);
                                goto bad_desc;
@@ -175,7 +174,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
                                goto bad_desc;
                        }
                        info->u = (void *) buf;
-                       if (info->u->bLength != sizeof *info->u) {
+                       if (info->u->bLength != sizeof(*info->u)) {
                                dev_dbg(&intf->dev, "CDC union len %u\n",
                                        info->u->bLength);
                                goto bad_desc;
@@ -233,7 +232,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
                                goto bad_desc;
                        }
                        info->ether = (void *) buf;
-                       if (info->ether->bLength != sizeof *info->ether) {
+                       if (info->ether->bLength != sizeof(*info->ether)) {
                                dev_dbg(&intf->dev, "CDC ether len %u\n",
                                        info->ether->bLength);
                                goto bad_desc;
@@ -274,8 +273,8 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
                        break;
                }
 next_desc:
-               len -= buf [0]; /* bLength */
-               buf += buf [0];
+               len -= buf[0];  /* bLength */
+               buf += buf[0];
        }
 
        /* Microsoft ActiveSync based and some regular RNDIS devices lack the
@@ -379,9 +378,7 @@ void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf)
 }
 EXPORT_SYMBOL_GPL(usbnet_cdc_unbind);
 
-/*-------------------------------------------------------------------------
- *
- * Communications Device Class, Ethernet Control model
+/* Communications Device Class, Ethernet Control model
  *
  * Takes two interfaces.  The DATA interface is inactive till an altsetting
  * is selected.  Configuration data includes class descriptors.  There's
@@ -389,8 +386,7 @@ EXPORT_SYMBOL_GPL(usbnet_cdc_unbind);
  *
  * This should interop with whatever the 2.4 "CDCEther.c" driver
  * (by Brad Hards) talked with, with more functionality.
- *
- *-------------------------------------------------------------------------*/
+ */
 
 static void dumpspeed(struct usbnet *dev, __le32 *speeds)
 {
@@ -404,7 +400,7 @@ void usbnet_cdc_status(struct usbnet *dev, struct urb *urb)
 {
        struct usb_cdc_notification     *event;
 
-       if (urb->actual_length < sizeof *event)
+       if (urb->actual_length < sizeof(*event))
                return;
 
        /* SPEED_CHANGE can get split into two 8-byte packets */
@@ -423,7 +419,7 @@ void usbnet_cdc_status(struct usbnet *dev, struct urb *urb)
        case USB_CDC_NOTIFY_SPEED_CHANGE:       /* tx/rx rates */
                netif_dbg(dev, timer, dev->net, "CDC: speed change (len %d)\n",
                          urb->actual_length);
-               if (urb->actual_length != (sizeof *event + 8))
+               if (urb->actual_length != (sizeof(*event) + 8))
                        set_bit(EVENT_STS_SPLIT, &dev->flags);
                else
                        dumpspeed(dev, (__le32 *) &event[1]);
@@ -469,7 +465,6 @@ EXPORT_SYMBOL_GPL(usbnet_cdc_bind);
 static const struct driver_info        cdc_info = {
        .description =  "CDC Ethernet Device",
        .flags =        FLAG_ETHER | FLAG_POINTTOPOINT,
-       // .check_connect = cdc_check_connect,
        .bind =         usbnet_cdc_bind,
        .unbind =       usbnet_cdc_unbind,
        .status =       usbnet_cdc_status,
@@ -493,9 +488,8 @@ static const struct driver_info wwan_info = {
 #define DELL_VENDOR_ID         0x413C
 #define REALTEK_VENDOR_ID      0x0bda
 
-static const struct usb_device_id      products [] = {
-/*
- * BLACKLIST !!
+static const struct usb_device_id      products[] = {
+/* BLACKLIST !!
  *
  * First blacklist any products that are egregiously nonconformant
  * with the CDC Ethernet specs.  Minor braindamage we cope with; when
@@ -542,7 +536,7 @@ static const struct usb_device_id   products [] = {
        .driver_info            = 0,
 }, {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
-                 | USB_DEVICE_ID_MATCH_DEVICE,
+                         | USB_DEVICE_ID_MATCH_DEVICE,
        .idVendor               = 0x04DD,
        .idProduct              = 0x8007,       /* C-700 */
        ZAURUS_MASTER_INTERFACE,
@@ -659,8 +653,7 @@ static const struct usb_device_id   products [] = {
        .driver_info = 0,
 },
 
-/*
- * WHITELIST!!!
+/* WHITELIST!!!
  *
  * CDC Ether uses two interfaces, not necessarily consecutive.
  * We match the main interface, ignoring the optional device
@@ -672,59 +665,39 @@ static const struct usb_device_id products [] = {
  */
 {
        /* ZTE (Vodafone) K3805-Z */
-       .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
-                | USB_DEVICE_ID_MATCH_PRODUCT
-                | USB_DEVICE_ID_MATCH_INT_INFO,
-       .idVendor               = ZTE_VENDOR_ID,
-       .idProduct              = 0x1003,
-       .bInterfaceClass        = USB_CLASS_COMM,
-       .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET,
-       .bInterfaceProtocol     = USB_CDC_PROTO_NONE,
+       USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1003, USB_CLASS_COMM,
+                                     USB_CDC_SUBCLASS_ETHERNET,
+                                     USB_CDC_PROTO_NONE),
        .driver_info = (unsigned long)&wwan_info,
 }, {
        /* ZTE (Vodafone) K3806-Z */
-       .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
-                | USB_DEVICE_ID_MATCH_PRODUCT
-                | USB_DEVICE_ID_MATCH_INT_INFO,
-       .idVendor               = ZTE_VENDOR_ID,
-       .idProduct              = 0x1015,
-       .bInterfaceClass        = USB_CLASS_COMM,
-       .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET,
-       .bInterfaceProtocol     = USB_CDC_PROTO_NONE,
+       USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1015, USB_CLASS_COMM,
+                                     USB_CDC_SUBCLASS_ETHERNET,
+                                     USB_CDC_PROTO_NONE),
        .driver_info = (unsigned long)&wwan_info,
 }, {
        /* ZTE (Vodafone) K4510-Z */
-       .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
-                | USB_DEVICE_ID_MATCH_PRODUCT
-                | USB_DEVICE_ID_MATCH_INT_INFO,
-       .idVendor               = ZTE_VENDOR_ID,
-       .idProduct              = 0x1173,
-       .bInterfaceClass        = USB_CLASS_COMM,
-       .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET,
-       .bInterfaceProtocol     = USB_CDC_PROTO_NONE,
+       USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1173, USB_CLASS_COMM,
+                                     USB_CDC_SUBCLASS_ETHERNET,
+                                     USB_CDC_PROTO_NONE),
        .driver_info = (unsigned long)&wwan_info,
 }, {
        /* ZTE (Vodafone) K3770-Z */
-       .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
-                | USB_DEVICE_ID_MATCH_PRODUCT
-                | USB_DEVICE_ID_MATCH_INT_INFO,
-       .idVendor               = ZTE_VENDOR_ID,
-       .idProduct              = 0x1177,
-       .bInterfaceClass        = USB_CLASS_COMM,
-       .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET,
-       .bInterfaceProtocol     = USB_CDC_PROTO_NONE,
+       USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1177, USB_CLASS_COMM,
+                                     USB_CDC_SUBCLASS_ETHERNET,
+                                     USB_CDC_PROTO_NONE),
        .driver_info = (unsigned long)&wwan_info,
 }, {
        /* ZTE (Vodafone) K3772-Z */
-       .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
-                | USB_DEVICE_ID_MATCH_PRODUCT
-                | USB_DEVICE_ID_MATCH_INT_INFO,
-       .idVendor               = ZTE_VENDOR_ID,
-       .idProduct              = 0x1181,
-       .bInterfaceClass        = USB_CLASS_COMM,
-       .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET,
-       .bInterfaceProtocol     = USB_CDC_PROTO_NONE,
+       USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1181, USB_CLASS_COMM,
+                                     USB_CDC_SUBCLASS_ETHERNET,
+                                     USB_CDC_PROTO_NONE),
        .driver_info = (unsigned long)&wwan_info,
+}, {
+       /* Telit modules */
+       USB_VENDOR_AND_INTERFACE_INFO(0x1bc7, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+       .driver_info = (kernel_ulong_t) &wwan_info,
 }, {
        USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
                        USB_CDC_PROTO_NONE),
@@ -736,15 +709,11 @@ static const struct usb_device_id products [] = {
 
 }, {
        /* Various Huawei modems with a network port like the UMG1831 */
-       .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
-                | USB_DEVICE_ID_MATCH_INT_INFO,
-       .idVendor               = HUAWEI_VENDOR_ID,
-       .bInterfaceClass        = USB_CLASS_COMM,
-       .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET,
-       .bInterfaceProtocol     = 255,
+       USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_COMM,
+                                     USB_CDC_SUBCLASS_ETHERNET, 255),
        .driver_info = (unsigned long)&wwan_info,
 },
-       { },            // END
+       { },            /* END */
 };
 MODULE_DEVICE_TABLE(usb, products);
 
index 2dbb9460349d3659fc738eabb35f01cb0022e049..c6867f926cffc18a981c7682e5493ae36924d988 100644 (file)
@@ -303,7 +303,7 @@ static void dm9601_set_multicast(struct net_device *net)
                rx_ctl |= 0x02;
        } else if (net->flags & IFF_ALLMULTI ||
                   netdev_mc_count(net) > DM_MAX_MCAST) {
-               rx_ctl |= 0x04;
+               rx_ctl |= 0x08;
        } else if (!netdev_mc_empty(net)) {
                struct netdev_hw_addr *ha;
 
index 6312332afeba283f192cfbf0b9ca07dfbb1e52ec..3d6aaf79d8b2399565b4e9c1a64edd4fe27b90af 100644 (file)
@@ -714,7 +714,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x2357, 0x0201, 4)},    /* TP-LINK HSUPA Modem MA180 */
        {QMI_FIXED_INTF(0x2357, 0x9000, 4)},    /* TP-LINK MA260 */
        {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},    /* Telit LE920 */
-       {QMI_FIXED_INTF(0x1e2d, 0x12d1, 4)},    /* Cinterion PLxx */
+       {QMI_FIXED_INTF(0x1e2d, 0x0060, 4)},    /* Cinterion PLxx */
 
        /* 4. Gobi 1000 devices */
        {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},    /* Acer Gobi Modem Device */
index 7b331e613e02aec22c3ac225e3a99c53c5f0f822..bf94e10a37c8e0121d783fc54c1b565b57a7ce21 100644 (file)
@@ -1241,7 +1241,9 @@ static int build_dma_sg(const struct sk_buff *skb, struct urb *urb)
        if (num_sgs == 1)
                return 0;
 
-       urb->sg = kmalloc(num_sgs * sizeof(struct scatterlist), GFP_ATOMIC);
+       /* reserve one for zero packet */
+       urb->sg = kmalloc((num_sgs + 1) * sizeof(struct scatterlist),
+                         GFP_ATOMIC);
        if (!urb->sg)
                return -ENOMEM;
 
@@ -1305,7 +1307,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
                if (build_dma_sg(skb, urb) < 0)
                        goto drop;
        }
-       entry->length = length = urb->transfer_buffer_length;
+       length = urb->transfer_buffer_length;
 
        /* don't assume the hardware handles USB_ZERO_PACKET
         * NOTE:  strictly conforming cdc-ether devices should expect
@@ -1317,15 +1319,18 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
        if (length % dev->maxpacket == 0) {
                if (!(info->flags & FLAG_SEND_ZLP)) {
                        if (!(info->flags & FLAG_MULTI_PACKET)) {
-                               urb->transfer_buffer_length++;
-                               if (skb_tailroom(skb)) {
+                               length++;
+                               if (skb_tailroom(skb) && !urb->num_sgs) {
                                        skb->data[skb->len] = 0;
                                        __skb_put(skb, 1);
-                               }
+                               } else if (urb->num_sgs)
+                                       sg_set_buf(&urb->sg[urb->num_sgs++],
+                                                       dev->padding_pkt, 1);
                        }
                } else
                        urb->transfer_flags |= URB_ZERO_PACKET;
        }
+       entry->length = urb->transfer_buffer_length = length;
 
        spin_lock_irqsave(&dev->txq.lock, flags);
        retval = usb_autopm_get_interface_async(dev->intf);
@@ -1509,6 +1514,7 @@ void usbnet_disconnect (struct usb_interface *intf)
 
        usb_kill_urb(dev->interrupt);
        usb_free_urb(dev->interrupt);
+       kfree(dev->padding_pkt);
 
        free_netdev(net);
 }
@@ -1679,9 +1685,16 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
        /* initialize max rx_qlen and tx_qlen */
        usbnet_update_max_qlen(dev);
 
+       if (dev->can_dma_sg && !(info->flags & FLAG_SEND_ZLP) &&
+               !(info->flags & FLAG_MULTI_PACKET)) {
+               dev->padding_pkt = kzalloc(1, GFP_KERNEL);
+               if (!dev->padding_pkt)
+                       goto out4;
+       }
+
        status = register_netdev (net);
        if (status)
-               goto out4;
+               goto out5;
        netif_info(dev, probe, dev->net,
                   "register '%s' at usb-%s-%s, %s, %pM\n",
                   udev->dev.driver->name,
@@ -1699,6 +1712,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
 
        return 0;
 
+out5:
+       kfree(dev->padding_pkt);
 out4:
        usb_free_urb(dev->interrupt);
 out3:
index bf64b4191dcc379f8d0c3d9ec287bb998efa6a69..2ef5b6219f3f46db28cb1256ce6eaa8fffc0bb3c 100644 (file)
@@ -564,7 +564,7 @@ static void vxlan_notify_add_rx_port(struct sock *sk)
        struct net_device *dev;
        struct net *net = sock_net(sk);
        sa_family_t sa_family = sk->sk_family;
-       u16 port = htons(inet_sk(sk)->inet_sport);
+       __be16 port = inet_sk(sk)->inet_sport;
 
        rcu_read_lock();
        for_each_netdev_rcu(net, dev) {
@@ -581,7 +581,7 @@ static void vxlan_notify_del_rx_port(struct sock *sk)
        struct net_device *dev;
        struct net *net = sock_net(sk);
        sa_family_t sa_family = sk->sk_family;
-       u16 port = htons(inet_sk(sk)->inet_sport);
+       __be16 port = inet_sk(sk)->inet_sport;
 
        rcu_read_lock();
        for_each_netdev_rcu(net, dev) {
@@ -952,8 +952,7 @@ void vxlan_sock_release(struct vxlan_sock *vs)
 
        spin_lock(&vn->sock_lock);
        hlist_del_rcu(&vs->hlist);
-       smp_wmb();
-       vs->sock->sk->sk_user_data = NULL;
+       rcu_assign_sk_user_data(vs->sock->sk, NULL);
        vxlan_notify_del_rx_port(sk);
        spin_unlock(&vn->sock_lock);
 
@@ -1048,8 +1047,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 
        port = inet_sk(sk)->inet_sport;
 
-       smp_read_barrier_depends();
-       vs = (struct vxlan_sock *)sk->sk_user_data;
+       vs = rcu_dereference_sk_user_data(sk);
        if (!vs)
                goto drop;
 
@@ -2021,7 +2019,8 @@ static struct device_type vxlan_type = {
 };
 
 /* Calls the ndo_add_vxlan_port of the caller in order to
- * supply the listening VXLAN udp ports.
+ * supply the listening VXLAN udp ports. Callers are expected
+ * to implement the ndo_add_vxlan_port.
  */
 void vxlan_get_rx_port(struct net_device *dev)
 {
@@ -2029,16 +2028,13 @@ void vxlan_get_rx_port(struct net_device *dev)
        struct net *net = dev_net(dev);
        struct vxlan_net *vn = net_generic(net, vxlan_net_id);
        sa_family_t sa_family;
-       u16 port;
-       int i;
-
-       if (!dev || !dev->netdev_ops || !dev->netdev_ops->ndo_add_vxlan_port)
-               return;
+       __be16 port;
+       unsigned int i;
 
        spin_lock(&vn->sock_lock);
        for (i = 0; i < PORT_HASH_SIZE; ++i) {
-               hlist_for_each_entry_rcu(vs, vs_head(net, i), hlist) {
-                       port = htons(inet_sk(vs->sock->sk)->inet_sport);
+               hlist_for_each_entry_rcu(vs, &vn->sock_list[i], hlist) {
+                       port = inet_sk(vs->sock->sk)->inet_sport;
                        sa_family = vs->sock->sk->sk_family;
                        dev->netdev_ops->ndo_add_vxlan_port(dev, sa_family,
                                                            port);
@@ -2304,8 +2300,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port,
        atomic_set(&vs->refcnt, 1);
        vs->rcv = rcv;
        vs->data = data;
-       smp_wmb();
-       vs->sock->sk->sk_user_data = vs;
+       rcu_assign_sk_user_data(vs->sock->sk, vs);
 
        spin_lock(&vn->sock_lock);
        hlist_add_head_rcu(&vs->hlist, vs_head(net, port));
@@ -2492,15 +2487,19 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
 
        SET_ETHTOOL_OPS(dev, &vxlan_ethtool_ops);
 
-       /* create an fdb entry for default destination */
-       err = vxlan_fdb_create(vxlan, all_zeros_mac,
-                              &vxlan->default_dst.remote_ip,
-                              NUD_REACHABLE|NUD_PERMANENT,
-                              NLM_F_EXCL|NLM_F_CREATE,
-                              vxlan->dst_port, vxlan->default_dst.remote_vni,
-                              vxlan->default_dst.remote_ifindex, NTF_SELF);
-       if (err)
-               return err;
+       /* create an fdb entry for a valid default destination */
+       if (!vxlan_addr_any(&vxlan->default_dst.remote_ip)) {
+               err = vxlan_fdb_create(vxlan, all_zeros_mac,
+                                      &vxlan->default_dst.remote_ip,
+                                      NUD_REACHABLE|NUD_PERMANENT,
+                                      NLM_F_EXCL|NLM_F_CREATE,
+                                      vxlan->dst_port,
+                                      vxlan->default_dst.remote_vni,
+                                      vxlan->default_dst.remote_ifindex,
+                                      NTF_SELF);
+               if (err)
+                       return err;
+       }
 
        err = register_netdevice(dev);
        if (err) {
index 4ee472a5a4e4ee6e81b1c0ffc820b6f685fb7ad1..ab9e3a8410bc2065fff9cb58996645fbf67be4fc 100644 (file)
@@ -1269,13 +1269,6 @@ static void ath9k_antenna_check(struct ath_softc *sc,
        if (!(ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB))
                return;
 
-       /*
-        * All MPDUs in an aggregate will use the same LNA
-        * as the first MPDU.
-        */
-       if (rs->rs_isaggr && !rs->rs_firstaggr)
-               return;
-
        /*
         * Change the default rx antenna if rx diversity
         * chooses the other antenna 3 times in a row.
index 35b515fe3ffa41e00dc614b6590cc2eabead9de4..5ac713d2ff5d22dc6d976291c6d97098bfbceafd 100644 (file)
@@ -399,6 +399,7 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
        tbf->bf_buf_addr = bf->bf_buf_addr;
        memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len);
        tbf->bf_state = bf->bf_state;
+       tbf->bf_state.stale = false;
 
        return tbf;
 }
@@ -1389,11 +1390,15 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
                      u16 tid, u16 *ssn)
 {
        struct ath_atx_tid *txtid;
+       struct ath_txq *txq;
        struct ath_node *an;
        u8 density;
 
        an = (struct ath_node *)sta->drv_priv;
        txtid = ATH_AN_2_TID(an, tid);
+       txq = txtid->ac->txq;
+
+       ath_txq_lock(sc, txq);
 
        /* update ampdu factor/density, they may have changed. This may happen
         * in HT IBSS when a beacon with HT-info is received after the station
@@ -1417,6 +1422,8 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
        memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf));
        txtid->baw_head = txtid->baw_tail = 0;
 
+       ath_txq_unlock_complete(sc, txq);
+
        return 0;
 }
 
@@ -1555,8 +1562,10 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
                        __skb_unlink(bf->bf_mpdu, tid_q);
                        list_add_tail(&bf->list, &bf_q);
                        ath_set_rates(tid->an->vif, tid->an->sta, bf);
-                       ath_tx_addto_baw(sc, tid, bf);
-                       bf->bf_state.bf_type &= ~BUF_AGGR;
+                       if (bf_isampdu(bf)) {
+                               ath_tx_addto_baw(sc, tid, bf);
+                               bf->bf_state.bf_type &= ~BUF_AGGR;
+                       }
                        if (bf_tail)
                                bf_tail->bf_next = bf;
 
@@ -1950,7 +1959,9 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
                        if (bf_is_ampdu_not_probing(bf))
                                txq->axq_ampdu_depth++;
 
-                       bf = bf->bf_lastbf->bf_next;
+                       bf_last = bf->bf_lastbf;
+                       bf = bf_last->bf_next;
+                       bf_last->bf_next = NULL;
                }
        }
 }
index c51d2dc489e45bd3a9b2aac36bf9fa2130453e72..1d7982afc0ad6af6b1b32f92ae07fb9ef694f2e1 100644 (file)
@@ -1065,12 +1065,9 @@ static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
        /* Try to set the DMA mask. If it fails, try falling back to a
         * lower mask, as we can always also support a lower one. */
        while (1) {
-               err = dma_set_mask(dev->dev->dma_dev, mask);
-               if (!err) {
-                       err = dma_set_coherent_mask(dev->dev->dma_dev, mask);
-                       if (!err)
-                               break;
-               }
+               err = dma_set_mask_and_coherent(dev->dev->dma_dev, mask);
+               if (!err)
+                       break;
                if (mask == DMA_BIT_MASK(64)) {
                        mask = DMA_BIT_MASK(32);
                        fallback = true;
index 42eb26c99e11cea54a2b063de4120ec69ae33b22..b2ed1795130bb0d7e1f10f95ab9775743b5f276b 100644 (file)
@@ -806,12 +806,9 @@ static int b43legacy_dma_set_mask(struct b43legacy_wldev *dev, u64 mask)
        /* Try to set the DMA mask. If it fails, try falling back to a
         * lower mask, as we can always also support a lower one. */
        while (1) {
-               err = dma_set_mask(dev->dev->dma_dev, mask);
-               if (!err) {
-                       err = dma_set_coherent_mask(dev->dev->dma_dev, mask);
-                       if (!err)
-                               break;
-               }
+               err = dma_set_mask_and_coherent(dev->dev->dma_dev, mask);
+               if (!err)
+                       break;
                if (mask == DMA_BIT_MASK(64)) {
                        mask = DMA_BIT_MASK(32);
                        fallback = true;
index fc8a0fa6d3b2b111d555770727b9f0a405637308..b00a7e92225f7b928f5a3cf7395f860af27299bd 100644 (file)
@@ -28,7 +28,7 @@ config BRCMFMAC
 
 config BRCMFMAC_SDIO
        bool "SDIO bus interface support for FullMAC driver"
-       depends on MMC
+       depends on (MMC = y || MMC = BRCMFMAC)
        depends on BRCMFMAC
        select FW_LOADER
        default y
@@ -39,7 +39,7 @@ config BRCMFMAC_SDIO
 
 config BRCMFMAC_USB
        bool "USB bus interface support for FullMAC driver"
-       depends on USB
+       depends on (USB = y || USB = BRCMFMAC)
        depends on BRCMFMAC
        select FW_LOADER
        ---help---
index 64f4a2bc8ddedf6c131d8b8d70408acb3ba17d9b..c3462b75bd080d4f7e9d72dd979f86bd5c894319 100644 (file)
@@ -464,8 +464,6 @@ static struct sdio_driver brcmf_sdmmc_driver = {
 
 static int brcmf_sdio_pd_probe(struct platform_device *pdev)
 {
-       int ret;
-
        brcmf_dbg(SDIO, "Enter\n");
 
        brcmfmac_sdio_pdata = pdev->dev.platform_data;
@@ -473,11 +471,7 @@ static int brcmf_sdio_pd_probe(struct platform_device *pdev)
        if (brcmfmac_sdio_pdata->power_on)
                brcmfmac_sdio_pdata->power_on();
 
-       ret = sdio_register_driver(&brcmf_sdmmc_driver);
-       if (ret)
-               brcmf_err("sdio_register_driver failed: %d\n", ret);
-
-       return ret;
+       return 0;
 }
 
 static int brcmf_sdio_pd_remove(struct platform_device *pdev)
@@ -500,6 +494,15 @@ static struct platform_driver brcmf_sdio_pd = {
        }
 };
 
+void brcmf_sdio_register(void)
+{
+       int ret;
+
+       ret = sdio_register_driver(&brcmf_sdmmc_driver);
+       if (ret)
+               brcmf_err("sdio_register_driver failed: %d\n", ret);
+}
+
 void brcmf_sdio_exit(void)
 {
        brcmf_dbg(SDIO, "Enter\n");
@@ -510,18 +513,13 @@ void brcmf_sdio_exit(void)
                sdio_unregister_driver(&brcmf_sdmmc_driver);
 }
 
-void brcmf_sdio_init(void)
+void __init brcmf_sdio_init(void)
 {
        int ret;
 
        brcmf_dbg(SDIO, "Enter\n");
 
        ret = platform_driver_probe(&brcmf_sdio_pd, brcmf_sdio_pd_probe);
-       if (ret == -ENODEV) {
-               brcmf_dbg(SDIO, "No platform data available, registering without.\n");
-               ret = sdio_register_driver(&brcmf_sdmmc_driver);
-       }
-
-       if (ret)
-               brcmf_err("driver registration failed: %d\n", ret);
+       if (ret == -ENODEV)
+               brcmf_dbg(SDIO, "No platform data available.\n");
 }
index f7c1985844e44c3ed0464a4e21588d538f693959..74156f84180ca19b87df7ff244358f0ab830dab3 100644 (file)
@@ -156,10 +156,11 @@ extern int brcmf_bus_start(struct device *dev);
 #ifdef CONFIG_BRCMFMAC_SDIO
 extern void brcmf_sdio_exit(void);
 extern void brcmf_sdio_init(void);
+extern void brcmf_sdio_register(void);
 #endif
 #ifdef CONFIG_BRCMFMAC_USB
 extern void brcmf_usb_exit(void);
-extern void brcmf_usb_init(void);
+extern void brcmf_usb_register(void);
 #endif
 
 #endif                         /* _BRCMF_BUS_H_ */
index e067aec1fbf113220d1a1054ca3dfceb027448a2..40e7f854e10f9634b44e4475b3c78cab02ea4dc9 100644 (file)
@@ -1231,21 +1231,23 @@ u32 brcmf_get_chip_info(struct brcmf_if *ifp)
        return bus->chip << 4 | bus->chiprev;
 }
 
-static void brcmf_driver_init(struct work_struct *work)
+static void brcmf_driver_register(struct work_struct *work)
 {
-       brcmf_debugfs_init();
-
 #ifdef CONFIG_BRCMFMAC_SDIO
-       brcmf_sdio_init();
+       brcmf_sdio_register();
 #endif
 #ifdef CONFIG_BRCMFMAC_USB
-       brcmf_usb_init();
+       brcmf_usb_register();
 #endif
 }
-static DECLARE_WORK(brcmf_driver_work, brcmf_driver_init);
+static DECLARE_WORK(brcmf_driver_work, brcmf_driver_register);
 
 static int __init brcmfmac_module_init(void)
 {
+       brcmf_debugfs_init();
+#ifdef CONFIG_BRCMFMAC_SDIO
+       brcmf_sdio_init();
+#endif
        if (!schedule_work(&brcmf_driver_work))
                return -EBUSY;
 
index 39e01a7c8556f2ce022bd5b8c545c2e2a615af5d..f4aea47e0730996ec059f02dbc1f2edaf98c04d1 100644 (file)
@@ -1539,7 +1539,7 @@ void brcmf_usb_exit(void)
        brcmf_release_fw(&fw_image_list);
 }
 
-void brcmf_usb_init(void)
+void brcmf_usb_register(void)
 {
        brcmf_dbg(USB, "Enter\n");
        INIT_LIST_HEAD(&fw_image_list);
index 3a6544710c8ab222cc126ef53d5f19143498cc9e..edc5d105ff980e40e1ad2221a4c7686f87b0cea1 100644 (file)
@@ -457,6 +457,8 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
        if (err != 0)
                brcms_err(wl->wlc->hw->d11core, "%s: brcms_up() returned %d\n",
                          __func__, err);
+
+       bcma_core_pci_power_save(wl->wlc->hw->d11core->bus, true);
        return err;
 }
 
@@ -479,6 +481,8 @@ static void brcms_ops_stop(struct ieee80211_hw *hw)
                return;
        }
 
+       bcma_core_pci_power_save(wl->wlc->hw->d11core->bus, false);
+
        /* put driver in down state */
        spin_lock_bh(&wl->lock);
        brcms_down(wl);
index d06376014bcda61bd73d92adeac2b4bf65640883..899cad34ccd3aa1649029d90294fe21c30608d14 100644 (file)
@@ -40,6 +40,7 @@ struct hwbus_priv {
        struct cw1200_common    *core;
        const struct cw1200_platform_data_spi *pdata;
        spinlock_t              lock; /* Serialize all bus operations */
+       wait_queue_head_t       wq;
        int claimed;
 };
 
@@ -197,8 +198,11 @@ static void cw1200_spi_lock(struct hwbus_priv *self)
 {
        unsigned long flags;
 
+       DECLARE_WAITQUEUE(wait, current);
+
        might_sleep();
 
+       add_wait_queue(&self->wq, &wait);
        spin_lock_irqsave(&self->lock, flags);
        while (1) {
                set_current_state(TASK_UNINTERRUPTIBLE);
@@ -211,6 +215,7 @@ static void cw1200_spi_lock(struct hwbus_priv *self)
        set_current_state(TASK_RUNNING);
        self->claimed = 1;
        spin_unlock_irqrestore(&self->lock, flags);
+       remove_wait_queue(&self->wq, &wait);
 
        return;
 }
@@ -222,6 +227,8 @@ static void cw1200_spi_unlock(struct hwbus_priv *self)
        spin_lock_irqsave(&self->lock, flags);
        self->claimed = 0;
        spin_unlock_irqrestore(&self->lock, flags);
+       wake_up(&self->wq);
+
        return;
 }
 
@@ -243,9 +250,10 @@ static int cw1200_spi_irq_subscribe(struct hwbus_priv *self)
 
        pr_debug("SW IRQ subscribe\n");
 
-       ret = request_any_context_irq(self->func->irq, cw1200_spi_irq_handler,
-                                     IRQF_TRIGGER_HIGH,
-                                     "cw1200_wlan_irq", self);
+       ret = request_threaded_irq(self->func->irq, NULL,
+                                  cw1200_spi_irq_handler,
+                                  IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+                                  "cw1200_wlan_irq", self);
        if (WARN_ON(ret < 0))
                goto exit;
 
@@ -400,6 +408,8 @@ static int cw1200_spi_probe(struct spi_device *func)
 
        spi_set_drvdata(func, self);
 
+       init_waitqueue_head(&self->wq);
+
        status = cw1200_spi_irq_subscribe(self);
 
        status = cw1200_core_probe(&cw1200_spi_hwbus_ops,
index 21c688264708316b34c51d196aa36fff5f5aaf01..1214c587fd08587f263b2c979eab9bc902b53ae1 100644 (file)
@@ -150,7 +150,7 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv,
  */
 int
 mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
-                         struct mwifiex_ra_list_tbl *pra_list, int headroom,
+                         struct mwifiex_ra_list_tbl *pra_list,
                          int ptrindex, unsigned long ra_list_flags)
                          __releases(&priv->wmm.ra_list_spinlock)
 {
@@ -160,6 +160,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
        int pad = 0, ret;
        struct mwifiex_tx_param tx_param;
        struct txpd *ptx_pd = NULL;
+       int headroom = adapter->iface_type == MWIFIEX_USB ? 0 : INTF_HEADER_LEN;
 
        skb_src = skb_peek(&pra_list->skb_head);
        if (!skb_src) {
index 900e1c62a0cceb4499457be3b76be7e9589be415..892098d6a69687dd2d8c1fc61612a6fb9999d754 100644 (file)
@@ -26,7 +26,7 @@
 int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv,
                                struct sk_buff *skb);
 int mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
-                             struct mwifiex_ra_list_tbl *ptr, int headroom,
+                             struct mwifiex_ra_list_tbl *ptr,
                              int ptr_index, unsigned long flags)
                              __releases(&priv->wmm.ra_list_spinlock);
 
index 2d761477d15e5761ed968200484a6fd55d066f39..a6c46f3b6e3a0d622b796f094b5b75016428438e 100644 (file)
@@ -1155,7 +1155,7 @@ int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
        uint32_t conditions = le32_to_cpu(phs_cfg->params.hs_config.conditions);
 
        if (phs_cfg->action == cpu_to_le16(HS_ACTIVATE) &&
-           adapter->iface_type == MWIFIEX_SDIO) {
+           adapter->iface_type != MWIFIEX_USB) {
                mwifiex_hs_activated_event(priv, true);
                return 0;
        } else {
@@ -1167,8 +1167,7 @@ int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
        }
        if (conditions != HS_CFG_CANCEL) {
                adapter->is_hs_configured = true;
-               if (adapter->iface_type == MWIFIEX_USB ||
-                   adapter->iface_type == MWIFIEX_PCIE)
+               if (adapter->iface_type == MWIFIEX_USB)
                        mwifiex_hs_activated_event(priv, true);
        } else {
                adapter->is_hs_configured = false;
index 2472d4b7f00e997bc9e6b21586edcf42fe692498..1c70b8d092270ba3a456664aaf6ec3e9da4b3b59 100644 (file)
@@ -447,9 +447,6 @@ static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message)
         */
        adapter->is_suspended = true;
 
-       for (i = 0; i < adapter->priv_num; i++)
-               netif_carrier_off(adapter->priv[i]->netdev);
-
        if (atomic_read(&card->rx_cmd_urb_pending) && card->rx_cmd.urb)
                usb_kill_urb(card->rx_cmd.urb);
 
@@ -509,10 +506,6 @@ static int mwifiex_usb_resume(struct usb_interface *intf)
                                                  MWIFIEX_RX_CMD_BUF_SIZE);
        }
 
-       for (i = 0; i < adapter->priv_num; i++)
-               if (adapter->priv[i]->media_connected)
-                       netif_carrier_on(adapter->priv[i]->netdev);
-
        /* Disable Host Sleep */
        if (adapter->hs_activated)
                mwifiex_cancel_hs(mwifiex_get_priv(adapter,
index 2e8f9cdea54d719cf0f25b4b29d816eb0709ff7a..95fa3599b4070b02aecc8d4d46073137b05c5b98 100644 (file)
@@ -1239,8 +1239,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
                if (enable_tx_amsdu && mwifiex_is_amsdu_allowed(priv, tid) &&
                    mwifiex_is_11n_aggragation_possible(priv, ptr,
                                                        adapter->tx_buf_size))
-                       mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN,
-                                                 ptr_index, flags);
+                       mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags);
                        /* ra_list_spinlock has been freed in
                           mwifiex_11n_aggregate_pkt() */
                else
index b9deef66cf4b8179893b918fbd0fb3365480a686..e328d3058c419a0c7c4c367fd7e62ada31ddded4 100644 (file)
@@ -83,6 +83,7 @@ static struct usb_device_id p54u_table[] = {
        {USB_DEVICE(0x06a9, 0x000e)},   /* Westell 802.11g USB (A90-211WG-01) */
        {USB_DEVICE(0x06b9, 0x0121)},   /* Thomson SpeedTouch 121g */
        {USB_DEVICE(0x0707, 0xee13)},   /* SMC 2862W-G version 2 */
+       {USB_DEVICE(0x07aa, 0x0020)},   /* Corega WLUSB2GTST USB */
        {USB_DEVICE(0x0803, 0x4310)},   /* Zoom 4410a */
        {USB_DEVICE(0x083a, 0x4521)},   /* Siemens Gigaset USB Adapter 54 version 2 */
        {USB_DEVICE(0x083a, 0x4531)},   /* T-Com Sinus 154 data II */
@@ -979,6 +980,7 @@ static int p54u_load_firmware(struct ieee80211_hw *dev,
        if (err) {
                dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s "
                                          "(%d)!\n", p54u_fwlist[i].fw, err);
+               usb_put_dev(udev);
        }
 
        return err;
index 95e6e61c3de0db729ec27e1eb4ce4f601faf7b1d..88ce656f96cda3d7ea1f7ae5756827538edfc6d2 100644 (file)
@@ -6659,19 +6659,20 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
                     rt2800_init_registers(rt2x00dev)))
                return -EIO;
 
+       if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev)))
+               return -EIO;
+
        /*
         * Send signal to firmware during boot time.
         */
        rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
        rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
-       if (rt2x00_is_usb(rt2x00dev)) {
+       if (rt2x00_is_usb(rt2x00dev))
                rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);
-               rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
-       }
+       rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
        msleep(1);
 
-       if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev) ||
-                    rt2800_wait_bbp_ready(rt2x00dev)))
+       if (unlikely(rt2800_wait_bbp_ready(rt2x00dev)))
                return -EIO;
 
        rt2800_init_bbp(rt2x00dev);
index 841fb9dfc9dadcc0d25e8017c8a11ba8505486fd..9a6edb0c014ec3526c5b4c260b8784cc8fd855d0 100644 (file)
@@ -438,17 +438,16 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev)
                skb_queue_tail(&priv->rx_queue, skb);
                usb_anchor_urb(entry, &priv->anchored);
                ret = usb_submit_urb(entry, GFP_KERNEL);
+               usb_put_urb(entry);
                if (ret) {
                        skb_unlink(skb, &priv->rx_queue);
                        usb_unanchor_urb(entry);
                        goto err;
                }
-               usb_free_urb(entry);
        }
        return ret;
 
 err:
-       usb_free_urb(entry);
        kfree_skb(skb);
        usb_kill_anchored_urbs(&priv->anchored);
        return ret;
@@ -956,8 +955,12 @@ static int rtl8187_start(struct ieee80211_hw *dev)
                                  (RETRY_COUNT << 8  /* short retry limit */) |
                                  (RETRY_COUNT << 0  /* long retry limit */) |
                                  (7 << 21 /* MAX TX DMA */));
-               rtl8187_init_urbs(dev);
-               rtl8187b_init_status_urb(dev);
+               ret = rtl8187_init_urbs(dev);
+               if (ret)
+                       goto rtl8187_start_exit;
+               ret = rtl8187b_init_status_urb(dev);
+               if (ret)
+                       usb_kill_anchored_urbs(&priv->anchored);
                goto rtl8187_start_exit;
        }
 
@@ -966,7 +969,9 @@ static int rtl8187_start(struct ieee80211_hw *dev)
        rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0);
        rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0);
 
-       rtl8187_init_urbs(dev);
+       ret = rtl8187_init_urbs(dev);
+       if (ret)
+               goto rtl8187_start_exit;
 
        reg = RTL818X_RX_CONF_ONLYERLPKT |
              RTL818X_RX_CONF_RX_AUTORESETPHY |
index cc03e7c87cbe739c9d762a6462b1b0b6f21e1795..703258742d28eefd339bde254d30661c4175b1a9 100644 (file)
@@ -2057,7 +2057,7 @@ struct rtl_priv {
           that it points to the data allocated
           beyond  this structure like:
           rtl_pci_priv or rtl_usb_priv */
-       u8 priv[0];
+       u8 priv[0] __aligned(sizeof(void *));
 };
 
 #define rtl_priv(hw)           (((struct rtl_priv *)(hw)->priv))
index a1977430ddfb9be616a6e97c7cfb4951da2cdd09..5715318d6bab3b4c7905c7c69ee549e39636c6cc 100644 (file)
@@ -184,6 +184,7 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
                   unsigned long rx_ring_ref, unsigned int tx_evtchn,
                   unsigned int rx_evtchn);
 void xenvif_disconnect(struct xenvif *vif);
+void xenvif_free(struct xenvif *vif);
 
 int xenvif_xenbus_init(void);
 void xenvif_xenbus_fini(void);
index 625c6f49cfba9923e80dc0834d49a6a6b870f1b3..01bb854c7f62bfc281dfdc0081829237f2f843d6 100644 (file)
@@ -353,6 +353,9 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
        }
 
        netdev_dbg(dev, "Successfully created xenvif\n");
+
+       __module_get(THIS_MODULE);
+
        return vif;
 }
 
@@ -366,8 +369,6 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
        if (vif->tx_irq)
                return 0;
 
-       __module_get(THIS_MODULE);
-
        err = xenvif_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref);
        if (err < 0)
                goto err;
@@ -406,7 +407,7 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
 
        init_waitqueue_head(&vif->wq);
        vif->task = kthread_create(xenvif_kthread,
-                                  (void *)vif, vif->dev->name);
+                                  (void *)vif, "%s", vif->dev->name);
        if (IS_ERR(vif->task)) {
                pr_warn("Could not allocate kthread for %s\n", vif->dev->name);
                err = PTR_ERR(vif->task);
@@ -452,12 +453,6 @@ void xenvif_carrier_off(struct xenvif *vif)
 
 void xenvif_disconnect(struct xenvif *vif)
 {
-       /* Disconnect funtion might get called by generic framework
-        * even before vif connects, so we need to check if we really
-        * need to do a module_put.
-        */
-       int need_module_put = 0;
-
        if (netif_carrier_ok(vif->dev))
                xenvif_carrier_off(vif);
 
@@ -468,23 +463,22 @@ void xenvif_disconnect(struct xenvif *vif)
                        unbind_from_irqhandler(vif->tx_irq, vif);
                        unbind_from_irqhandler(vif->rx_irq, vif);
                }
-               /* vif->irq is valid, we had a module_get in
-                * xenvif_connect.
-                */
-               need_module_put = 1;
+               vif->tx_irq = 0;
        }
 
        if (vif->task)
                kthread_stop(vif->task);
 
+       xenvif_unmap_frontend_rings(vif);
+}
+
+void xenvif_free(struct xenvif *vif)
+{
        netif_napi_del(&vif->napi);
 
        unregister_netdev(vif->dev);
 
-       xenvif_unmap_frontend_rings(vif);
-
        free_netdev(vif->dev);
 
-       if (need_module_put)
-               module_put(THIS_MODULE);
+       module_put(THIS_MODULE);
 }
index 956130c70036d2d3d297e8d101bc68017f19c9d6..f3e591c611ded744ec0b6ea2cefe9b7dd3d568c7 100644 (file)
@@ -212,6 +212,49 @@ static bool start_new_rx_buffer(int offset, unsigned long size, int head)
        return false;
 }
 
+struct xenvif_count_slot_state {
+       unsigned long copy_off;
+       bool head;
+};
+
+unsigned int xenvif_count_frag_slots(struct xenvif *vif,
+                                    unsigned long offset, unsigned long size,
+                                    struct xenvif_count_slot_state *state)
+{
+       unsigned count = 0;
+
+       offset &= ~PAGE_MASK;
+
+       while (size > 0) {
+               unsigned long bytes;
+
+               bytes = PAGE_SIZE - offset;
+
+               if (bytes > size)
+                       bytes = size;
+
+               if (start_new_rx_buffer(state->copy_off, bytes, state->head)) {
+                       count++;
+                       state->copy_off = 0;
+               }
+
+               if (state->copy_off + bytes > MAX_BUFFER_OFFSET)
+                       bytes = MAX_BUFFER_OFFSET - state->copy_off;
+
+               state->copy_off += bytes;
+
+               offset += bytes;
+               size -= bytes;
+
+               if (offset == PAGE_SIZE)
+                       offset = 0;
+
+               state->head = false;
+       }
+
+       return count;
+}
+
 /*
  * Figure out how many ring slots we're going to need to send @skb to
  * the guest. This function is essentially a dry run of
@@ -219,48 +262,39 @@ static bool start_new_rx_buffer(int offset, unsigned long size, int head)
  */
 unsigned int xenvif_count_skb_slots(struct xenvif *vif, struct sk_buff *skb)
 {
+       struct xenvif_count_slot_state state;
        unsigned int count;
-       int i, copy_off;
+       unsigned char *data;
+       unsigned i;
 
-       count = DIV_ROUND_UP(skb_headlen(skb), PAGE_SIZE);
+       state.head = true;
+       state.copy_off = 0;
 
-       copy_off = skb_headlen(skb) % PAGE_SIZE;
+       /* Slot for the first (partial) page of data. */
+       count = 1;
 
+       /* Need a slot for the GSO prefix for GSO extra data? */
        if (skb_shinfo(skb)->gso_size)
                count++;
 
-       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-               unsigned long size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
-               unsigned long offset = skb_shinfo(skb)->frags[i].page_offset;
-               unsigned long bytes;
-
-               offset &= ~PAGE_MASK;
-
-               while (size > 0) {
-                       BUG_ON(offset >= PAGE_SIZE);
-                       BUG_ON(copy_off > MAX_BUFFER_OFFSET);
-
-                       bytes = PAGE_SIZE - offset;
-
-                       if (bytes > size)
-                               bytes = size;
+       data = skb->data;
+       while (data < skb_tail_pointer(skb)) {
+               unsigned long offset = offset_in_page(data);
+               unsigned long size = PAGE_SIZE - offset;
 
-                       if (start_new_rx_buffer(copy_off, bytes, 0)) {
-                               count++;
-                               copy_off = 0;
-                       }
+               if (data + size > skb_tail_pointer(skb))
+                       size = skb_tail_pointer(skb) - data;
 
-                       if (copy_off + bytes > MAX_BUFFER_OFFSET)
-                               bytes = MAX_BUFFER_OFFSET - copy_off;
+               count += xenvif_count_frag_slots(vif, offset, size, &state);
 
-                       copy_off += bytes;
+               data += size;
+       }
 
-                       offset += bytes;
-                       size -= bytes;
+       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+               unsigned long size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
+               unsigned long offset = skb_shinfo(skb)->frags[i].page_offset;
 
-                       if (offset == PAGE_SIZE)
-                               offset = 0;
-               }
+               count += xenvif_count_frag_slots(vif, offset, size, &state);
        }
        return count;
 }
index 1fe48fe364ed919a1f011170949c5cd37f4ad905..b45bce20ad7624421b7500cff3ccfc5a49f9204f 100644 (file)
 struct backend_info {
        struct xenbus_device *dev;
        struct xenvif *vif;
+
+       /* This is the state that will be reflected in xenstore when any
+        * active hotplug script completes.
+        */
+       enum xenbus_state state;
+
        enum xenbus_state frontend_state;
        struct xenbus_watch hotplug_status_watch;
        u8 have_hotplug_status_watch:1;
@@ -42,7 +48,7 @@ static int netback_remove(struct xenbus_device *dev)
        if (be->vif) {
                kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
                xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
-               xenvif_disconnect(be->vif);
+               xenvif_free(be->vif);
                be->vif = NULL;
        }
        kfree(be);
@@ -136,6 +142,8 @@ static int netback_probe(struct xenbus_device *dev,
        if (err)
                goto fail;
 
+       be->state = XenbusStateInitWait;
+
        /* This kicks hotplug scripts, so do it immediately. */
        backend_create_xenvif(be);
 
@@ -208,15 +216,113 @@ static void backend_create_xenvif(struct backend_info *be)
        kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE);
 }
 
+static void backend_disconnect(struct backend_info *be)
+{
+       if (be->vif)
+               xenvif_disconnect(be->vif);
+}
 
-static void disconnect_backend(struct xenbus_device *dev)
+static void backend_connect(struct backend_info *be)
 {
-       struct backend_info *be = dev_get_drvdata(&dev->dev);
+       if (be->vif)
+               connect(be);
+}
 
-       if (be->vif) {
-               xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
-               xenvif_disconnect(be->vif);
-               be->vif = NULL;
+static inline void backend_switch_state(struct backend_info *be,
+                                       enum xenbus_state state)
+{
+       struct xenbus_device *dev = be->dev;
+
+       pr_debug("%s -> %s\n", dev->nodename, xenbus_strstate(state));
+       be->state = state;
+
+       /* If we are waiting for a hotplug script then defer the
+        * actual xenbus state change.
+        */
+       if (!be->have_hotplug_status_watch)
+               xenbus_switch_state(dev, state);
+}
+
+/* Handle backend state transitions:
+ *
+ * The backend state starts in InitWait and the following transitions are
+ * allowed.
+ *
+ * InitWait -> Connected
+ *
+ *    ^    \         |
+ *    |     \        |
+ *    |      \       |
+ *    |       \      |
+ *    |        \     |
+ *    |         \    |
+ *    |          V   V
+ *
+ *  Closed  <-> Closing
+ *
+ * The state argument specifies the eventual state of the backend and the
+ * function transitions to that state via the shortest path.
+ */
+static void set_backend_state(struct backend_info *be,
+                             enum xenbus_state state)
+{
+       while (be->state != state) {
+               switch (be->state) {
+               case XenbusStateClosed:
+                       switch (state) {
+                       case XenbusStateInitWait:
+                       case XenbusStateConnected:
+                               pr_info("%s: prepare for reconnect\n",
+                                       be->dev->nodename);
+                               backend_switch_state(be, XenbusStateInitWait);
+                               break;
+                       case XenbusStateClosing:
+                               backend_switch_state(be, XenbusStateClosing);
+                               break;
+                       default:
+                               BUG();
+                       }
+                       break;
+               case XenbusStateInitWait:
+                       switch (state) {
+                       case XenbusStateConnected:
+                               backend_connect(be);
+                               backend_switch_state(be, XenbusStateConnected);
+                               break;
+                       case XenbusStateClosing:
+                       case XenbusStateClosed:
+                               backend_switch_state(be, XenbusStateClosing);
+                               break;
+                       default:
+                               BUG();
+                       }
+                       break;
+               case XenbusStateConnected:
+                       switch (state) {
+                       case XenbusStateInitWait:
+                       case XenbusStateClosing:
+                       case XenbusStateClosed:
+                               backend_disconnect(be);
+                               backend_switch_state(be, XenbusStateClosing);
+                               break;
+                       default:
+                               BUG();
+                       }
+                       break;
+               case XenbusStateClosing:
+                       switch (state) {
+                       case XenbusStateInitWait:
+                       case XenbusStateConnected:
+                       case XenbusStateClosed:
+                               backend_switch_state(be, XenbusStateClosed);
+                               break;
+                       default:
+                               BUG();
+                       }
+                       break;
+               default:
+                       BUG();
+               }
        }
 }
 
@@ -228,42 +334,33 @@ static void frontend_changed(struct xenbus_device *dev,
 {
        struct backend_info *be = dev_get_drvdata(&dev->dev);
 
-       pr_debug("frontend state %s\n", xenbus_strstate(frontend_state));
+       pr_debug("%s -> %s\n", dev->otherend, xenbus_strstate(frontend_state));
 
        be->frontend_state = frontend_state;
 
        switch (frontend_state) {
        case XenbusStateInitialising:
-               if (dev->state == XenbusStateClosed) {
-                       pr_info("%s: prepare for reconnect\n", dev->nodename);
-                       xenbus_switch_state(dev, XenbusStateInitWait);
-               }
+               set_backend_state(be, XenbusStateInitWait);
                break;
 
        case XenbusStateInitialised:
                break;
 
        case XenbusStateConnected:
-               if (dev->state == XenbusStateConnected)
-                       break;
-               backend_create_xenvif(be);
-               if (be->vif)
-                       connect(be);
+               set_backend_state(be, XenbusStateConnected);
                break;
 
        case XenbusStateClosing:
-               if (be->vif)
-                       kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
-               disconnect_backend(dev);
-               xenbus_switch_state(dev, XenbusStateClosing);
+               set_backend_state(be, XenbusStateClosing);
                break;
 
        case XenbusStateClosed:
-               xenbus_switch_state(dev, XenbusStateClosed);
+               set_backend_state(be, XenbusStateClosed);
                if (xenbus_dev_is_online(dev))
                        break;
                /* fall through if not online */
        case XenbusStateUnknown:
+               set_backend_state(be, XenbusStateClosed);
                device_unregister(&dev->dev);
                break;
 
@@ -356,7 +453,9 @@ static void hotplug_status_changed(struct xenbus_watch *watch,
        if (IS_ERR(str))
                return;
        if (len == sizeof("connected")-1 && !memcmp(str, "connected", len)) {
-               xenbus_switch_state(be->dev, XenbusStateConnected);
+               /* Complete any pending state change */
+               xenbus_switch_state(be->dev, be->state);
+
                /* Not interested in this watch anymore. */
                unregister_hotplug_status_watch(be);
        }
@@ -386,12 +485,8 @@ static void connect(struct backend_info *be)
        err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch,
                                   hotplug_status_changed,
                                   "%s/%s", dev->nodename, "hotplug-status");
-       if (err) {
-               /* Switch now, since we can't do a watch. */
-               xenbus_switch_state(dev, XenbusStateConnected);
-       } else {
+       if (!err)
                be->have_hotplug_status_watch = 1;
-       }
 
        netif_wake_queue(be->vif->dev);
 }
index 9b439ac63d8e73eef85aa490d5cab6ec825120b7..54382ba4a6e9bf71f5dd2227283ff8e926948cb1 100644 (file)
@@ -284,9 +284,6 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
        else
                of_device_make_bus_id(&dev->dev);
 
-       /* setup amba-specific device info */
-       dev->dma_mask = ~0;
-
        /* Allow the HW Peripheral ID to be overridden */
        prop = of_get_property(node, "arm,primecell-periphid", NULL);
        if (prop)
index 903e1285fda06ce30c84bf79b44078e733048c38..9637615262296235737a094282645b72f3c6ccc5 100644 (file)
@@ -2004,6 +2004,7 @@ struct parport *parport_pc_probe_port(unsigned long int base,
        struct resource *ECR_res = NULL;
        struct resource *EPP_res = NULL;
        struct platform_device *pdev = NULL;
+       int ret;
 
        if (!dev) {
                /* We need a physical device to attach to, but none was
@@ -2014,8 +2015,11 @@ struct parport *parport_pc_probe_port(unsigned long int base,
                        return NULL;
                dev = &pdev->dev;
 
-               dev->coherent_dma_mask = DMA_BIT_MASK(24);
-               dev->dma_mask = &dev->coherent_dma_mask;
+               ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(24));
+               if (ret) {
+                       dev_err(dev, "Unable to set coherent dma mask: disabling DMA\n");
+                       dma = PARPORT_DMA_NONE;
+               }
        }
 
        ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL);
index 7c29ee4ed0ae5559077b7b4efd69eb7ff2fd871a..b0299e6d9a3f2d1359f78454eb67e399ea6d3eb1 100644 (file)
@@ -47,6 +47,9 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
        if (event != ACPI_NOTIFY_DEVICE_WAKE || !pci_dev)
                return;
 
+       if (pci_dev->pme_poll)
+               pci_dev->pme_poll = false;
+
        if (pci_dev->current_state == PCI_D3cold) {
                pci_wakeup_event(pci_dev);
                pm_runtime_resume(&pci_dev->dev);
@@ -57,9 +60,6 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
        if (pci_dev->pme_support)
                pci_check_pme_status(pci_dev);
 
-       if (pci_dev->pme_poll)
-               pci_dev->pme_poll = false;
-
        pci_wakeup_event(pci_dev);
        pm_runtime_resume(&pci_dev->dev);
 
index e8ccf6c0f08a3d4d5a9b03aec428efddcba77c6f..bdd64b1b4817f7223fa31db19a118db5a9caaaa5 100644 (file)
@@ -1155,8 +1155,14 @@ static void pci_enable_bridge(struct pci_dev *dev)
 
        pci_enable_bridge(dev->bus->self);
 
-       if (pci_is_enabled(dev))
+       if (pci_is_enabled(dev)) {
+               if (!dev->is_busmaster) {
+                       dev_warn(&dev->dev, "driver skip pci_set_master, fix it!\n");
+                       pci_set_master(dev);
+               }
                return;
+       }
+
        retval = pci_enable_device(dev);
        if (retval)
                dev_err(&dev->dev, "Error enabling bridge (%d), continuing\n",
index a138965c01cbc6e4029615bc080790d2338e59e2..b8fcc38c0d116a97cf2b6f4142b026f8b8f94afb 100644 (file)
@@ -490,7 +490,7 @@ exit:
  * <devicename> <state> <pinname> are values that should match the pinctrl-maps
  * <newvalue> reflects the new config and is driver dependant
  */
-static int pinconf_dbg_config_write(struct file *file,
+static ssize_t pinconf_dbg_config_write(struct file *file,
        const char __user *user_buf, size_t count, loff_t *ppos)
 {
        struct pinctrl_maps *maps_node;
@@ -508,7 +508,7 @@ static int pinconf_dbg_config_write(struct file *file,
        int i;
 
        /* Get userspace string and assure termination */
-       buf_size = min(count, (size_t)(sizeof(buf)-1));
+       buf_size = min(count, sizeof(buf) - 1);
        if (copy_from_user(buf, user_buf, buf_size))
                return -EFAULT;
        buf[buf_size] = 0;
index 2689f8d01a1e202d72f226743e0ec8bcdba2b1d8..155b1b3a0e7a71597d26d3c0c1cab2a525a9ee19 100644 (file)
@@ -663,18 +663,18 @@ static void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
 /* pin banks of s5pv210 pin-controller */
 static struct samsung_pin_bank s5pv210_pin_bank[] = {
        EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
-       EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
+       EXYNOS_PIN_BANK_EINTG(4, 0x020, "gpa1", 0x04),
        EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08),
        EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c),
        EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10),
        EXYNOS_PIN_BANK_EINTG(4, 0x0a0, "gpd0", 0x14),
-       EXYNOS_PIN_BANK_EINTG(4, 0x0c0, "gpd1", 0x18),
-       EXYNOS_PIN_BANK_EINTG(5, 0x0e0, "gpe0", 0x1c),
-       EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpe1", 0x20),
-       EXYNOS_PIN_BANK_EINTG(6, 0x120, "gpf0", 0x24),
+       EXYNOS_PIN_BANK_EINTG(6, 0x0c0, "gpd1", 0x18),
+       EXYNOS_PIN_BANK_EINTG(8, 0x0e0, "gpe0", 0x1c),
+       EXYNOS_PIN_BANK_EINTG(5, 0x100, "gpe1", 0x20),
+       EXYNOS_PIN_BANK_EINTG(8, 0x120, "gpf0", 0x24),
        EXYNOS_PIN_BANK_EINTG(8, 0x140, "gpf1", 0x28),
        EXYNOS_PIN_BANK_EINTG(8, 0x160, "gpf2", 0x2c),
-       EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf3", 0x30),
+       EXYNOS_PIN_BANK_EINTG(6, 0x180, "gpf3", 0x30),
        EXYNOS_PIN_BANK_EINTG(7, 0x1a0, "gpg0", 0x34),
        EXYNOS_PIN_BANK_EINTG(7, 0x1c0, "gpg1", 0x38),
        EXYNOS_PIN_BANK_EINTG(7, 0x1e0, "gpg2", 0x3c),
index 82638fac3cfa6a3f40c6ce1f423d3146a5b29e02..30c4d356cb33510a550aec1d467ac40936552a60 100644 (file)
@@ -891,9 +891,10 @@ static int palmas_pinconf_set(struct pinctrl_dev *pctldev,
                param = pinconf_to_config_param(configs[i]);
                param_val = pinconf_to_config_argument(configs[i]);
 
+               if (param == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
+                       continue;
+
                switch (param) {
-               case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
-                       return 0;
                case PIN_CONFIG_BIAS_DISABLE:
                case PIN_CONFIG_BIAS_PULL_UP:
                case PIN_CONFIG_BIAS_PULL_DOWN:
index 622c4854977e63471b6e77cd950184a3dd3f13f8..93c9e3899d5e4a0230e91a7269c68b7d7d8433f4 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2012-2013, NVIDIA CORPORATION.  All rights reserved.
  *
- * Arthur:  Pritesh Raithatha <praithatha@nvidia.com>
+ * Author:  Pritesh Raithatha <praithatha@nvidia.com>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -2763,7 +2763,6 @@ static struct platform_driver tegra114_pinctrl_driver = {
 };
 module_platform_driver(tegra114_pinctrl_driver);
 
-MODULE_ALIAS("platform:tegra114-pinctrl");
 MODULE_AUTHOR("Pritesh Raithatha <praithatha@nvidia.com>");
-MODULE_DESCRIPTION("NVIDIA Tegra114 pincontrol driver");
+MODULE_DESCRIPTION("NVIDIA Tegra114 pinctrl driver");
 MODULE_LICENSE("GPL v2");
index 1a78163907734be9e1e49bd3bca6e2fc19e7b6c7..b9f2653e4ef90f315de25752fe24821a98497848 100644 (file)
@@ -709,7 +709,7 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
                struct of_regulator_match **da9063_reg_matches)
 {
        da9063_reg_matches = NULL;
-       return PTR_ERR(-ENODEV);
+       return ERR_PTR(-ENODEV);
 }
 #endif
 
index 488dfe7ce9a6c048a751029451df59d6f6f2c074..7e2b165972e6edd6e3eee6b26478cb263db5d048 100644 (file)
@@ -201,13 +201,7 @@ static unsigned int palmas_smps_ramp_delay[4] = {0, 10000, 5000, 2500};
 #define SMPS_CTRL_MODE_ECO             0x02
 #define SMPS_CTRL_MODE_PWM             0x03
 
-/* These values are derived from the data sheet. And are the number of steps
- * where there is a voltage change, the ranges at beginning and end of register
- * max/min values where there are no change are ommitted.
- *
- * So they are basically (maxV-minV)/stepV
- */
-#define PALMAS_SMPS_NUM_VOLTAGES       117
+#define PALMAS_SMPS_NUM_VOLTAGES       122
 #define PALMAS_SMPS10_NUM_VOLTAGES     2
 #define PALMAS_LDO_NUM_VOLTAGES                50
 
@@ -979,6 +973,7 @@ static int palmas_regulators_probe(struct platform_device *pdev)
                        pmic->desc[id].min_uV = 900000;
                        pmic->desc[id].uV_step = 50000;
                        pmic->desc[id].linear_min_sel = 1;
+                       pmic->desc[id].enable_time = 500;
                        pmic->desc[id].vsel_reg =
                                        PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
                                                palmas_regs_info[id].vsel_addr);
@@ -997,6 +992,11 @@ static int palmas_regulators_probe(struct platform_device *pdev)
                                pmic->desc[id].min_uV = 450000;
                                pmic->desc[id].uV_step = 25000;
                        }
+
+                       /* LOD6 in vibrator mode will have enable time 2000us */
+                       if (pdata && pdata->ldo6_vibrator &&
+                               (id == PALMAS_REG_LDO6))
+                               pmic->desc[id].enable_time = 2000;
                } else {
                        pmic->desc[id].n_voltages = 1;
                        pmic->desc[id].ops = &palmas_ops_extreg;
index d8e3e1262bc2960b4eebf89b5c552ef6e04df305..20c271d49dcbbd358e03d5140d05e9da4ca54952 100644 (file)
@@ -279,8 +279,12 @@ static int ti_abb_set_opp(struct regulator_dev *rdev, struct ti_abb *abb,
        ti_abb_rmw(regs->opp_sel_mask, info->opp_sel, regs->control_reg,
                   abb->base);
 
-       /* program LDO VBB vset override if needed */
-       if (abb->ldo_base)
+       /*
+        * program LDO VBB vset override if needed for !bypass mode
+        * XXX: Do not switch sequence - for !bypass, LDO override reset *must*
+        * be performed *before* switch to bias mode else VBB glitches.
+        */
+       if (abb->ldo_base && info->opp_sel != TI_ABB_NOMINAL_OPP)
                ti_abb_program_ldovbb(dev, abb, info);
 
        /* Initiate ABB ldo change */
@@ -295,6 +299,14 @@ static int ti_abb_set_opp(struct regulator_dev *rdev, struct ti_abb *abb,
        if (ret)
                goto out;
 
+       /*
+        * Reset LDO VBB vset override bypass mode
+        * XXX: Do not switch sequence - for bypass, LDO override reset *must*
+        * be performed *after* switch to bypass else VBB glitches.
+        */
+       if (abb->ldo_base && info->opp_sel == TI_ABB_NOMINAL_OPP)
+               ti_abb_program_ldovbb(dev, abb, info);
+
 out:
        return ret;
 }
index 1432b26ef2e97b0830a2ecf973789ee20b7991cc..2205fbc2c37b4cf9b917bafa5d1f583f7e767b49 100644 (file)
@@ -63,7 +63,7 @@ static irqreturn_t wm831x_ldo_uv_irq(int irq, void *data)
  */
 
 static const struct regulator_linear_range wm831x_gp_ldo_ranges[] = {
-       { .min_uV =  900000, .max_uV = 1650000, .min_sel =  0, .max_sel = 14,
+       { .min_uV =  900000, .max_uV = 1600000, .min_sel =  0, .max_sel = 14,
          .uV_step =  50000 },
        { .min_uV = 1700000, .max_uV = 3300000, .min_sel = 15, .max_sel = 31,
          .uV_step = 100000 },
@@ -332,7 +332,7 @@ static struct platform_driver wm831x_gp_ldo_driver = {
  */
 
 static const struct regulator_linear_range wm831x_aldo_ranges[] = {
-       { .min_uV = 1000000, .max_uV = 1650000, .min_sel =  0, .max_sel = 12,
+       { .min_uV = 1000000, .max_uV = 1600000, .min_sel =  0, .max_sel = 12,
          .uV_step =  50000 },
        { .min_uV = 1700000, .max_uV = 3500000, .min_sel = 13, .max_sel = 31,
          .uV_step = 100000 },
index 835b5f0f344ed2537115b1ed486d14860f88434e..61ca9292a42944229f9f52bc6f5b8943b6414b22 100644 (file)
@@ -543,7 +543,7 @@ static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev,
 }
 
 static const struct regulator_linear_range wm8350_ldo_ranges[] = {
-       { .min_uV =  900000, .max_uV = 1750000, .min_sel =  0, .max_sel = 15,
+       { .min_uV =  900000, .max_uV = 1650000, .min_sel =  0, .max_sel = 15,
          .uV_step =  50000 },
        { .min_uV = 1800000, .max_uV = 3300000, .min_sel = 16, .max_sel = 31,
          .uV_step = 100000 },
index 08b22a901c2590e3aca12ebcfe4484e143c54460..d7ca9305ff457037089e1edba2cc33b28bec1073 100644 (file)
 #define BNX2FC_RQ_WQE_SIZE             (BNX2FC_RQ_BUF_SZ)
 #define BNX2FC_XFERQ_WQE_SIZE          (sizeof(struct fcoe_xfrqe))
 #define BNX2FC_CONFQ_WQE_SIZE          (sizeof(struct fcoe_confqe))
-#define BNX2FC_5771X_DB_PAGE_SIZE      128
+#define BNX2X_DB_SHIFT                 3
 
 #define BNX2FC_TASK_SIZE               128
 #define        BNX2FC_TASKS_PER_PAGE           (PAGE_SIZE/BNX2FC_TASK_SIZE)
index c0d035a8f8f9e79a08a0b313742c2f7b0009ca6f..46a37657307fd9dae74e800709f80f2140da65a5 100644 (file)
@@ -1421,8 +1421,7 @@ int bnx2fc_map_doorbell(struct bnx2fc_rport *tgt)
 
        reg_base = pci_resource_start(hba->pcidev,
                                        BNX2X_DOORBELL_PCI_BAR);
-       reg_off = BNX2FC_5771X_DB_PAGE_SIZE *
-                       (context_id & 0x1FFFF) + DPM_TRIGER_TYPE;
+       reg_off = (1 << BNX2X_DB_SHIFT) * (context_id & 0x1FFFF);
        tgt->ctx_base = ioremap_nocache(reg_base + reg_off, 4);
        if (!tgt->ctx_base)
                return -ENOMEM;
index 6940f0930a848d0523249c2e695345dfe49ecf88..c73bbcb63c02049b1147b98829d8a3e4b4c8ebf5 100644 (file)
@@ -64,7 +64,7 @@
 #define MAX_PAGES_PER_CTRL_STRUCT_POOL 8
 #define BNX2I_RESERVED_SLOW_PATH_CMD_SLOTS     4
 
-#define BNX2I_5771X_DBELL_PAGE_SIZE    128
+#define BNX2X_DB_SHIFT                 3
 
 /* 5706/08 hardware has limit on maximum buffer size per BD it can handle */
 #define MAX_BD_LENGTH                  65535
index af3e675d4d48fb51b4f01bdf7acf2f9b6b3c17d6..5be718c241c4f329edb1c23e684daa7b4681a0f1 100644 (file)
@@ -2738,8 +2738,7 @@ int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep)
        if (test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) {
                reg_base = pci_resource_start(ep->hba->pcidev,
                                              BNX2X_DOORBELL_PCI_BAR);
-               reg_off = BNX2I_5771X_DBELL_PAGE_SIZE * (cid_num & 0x1FFFF) +
-                         DPM_TRIGER_TYPE;
+               reg_off = (1 << BNX2X_DB_SHIFT) * (cid_num & 0x1FFFF);
                ep->qp.ctx_base = ioremap_nocache(reg_base + reg_off, 4);
                goto arm_cq;
        }
index d1549b74e2d1b91eeb4f8ebf459ec4f13db73275..7bd7f0d5f050a2ece3f176b1f05ca2f8936270a3 100644 (file)
@@ -1684,7 +1684,7 @@ u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost)
 
        host_dev = scsi_get_device(shost);
        if (host_dev && host_dev->dma_mask)
-               bounce_limit = *host_dev->dma_mask;
+               bounce_limit = dma_max_pfn(host_dev) << PAGE_SHIFT;
 
        return bounce_limit;
 }
index a84aab47a11315b137d370a9337a8f5d722bb644..f73287eab373a92b7f1a9876c3e53eb7f2cee327 100644 (file)
@@ -96,6 +96,15 @@ config COMEDI_SKEL
          To compile this driver as a module, choose M here: the module will be
          called skel.
 
+config COMEDI_SSV_DNP
+       tristate "SSV Embedded Systems DIL/Net-PC support"
+       depends on X86_32 || COMPILE_TEST
+       ---help---
+         Enable support for SSV Embedded Systems DIL/Net-PC
+
+         To compile this driver as a module, choose M here: the module will be
+         called ssv_dnp.
+
 endif # COMEDI_MISC_DRIVERS
 
 menuconfig COMEDI_ISA_DRIVERS
@@ -386,6 +395,14 @@ config COMEDI_DMM32AT
          To compile this driver as a module, choose M here: the module will be
          called dmm32at.
 
+config COMEDI_UNIOXX5
+       tristate "Fastwel UNIOxx-5 analog and digital io board support"
+       ---help---
+         Enable support for Fastwel UNIOxx-5 (analog and digital i/o) boards
+
+         To compile this driver as a module, choose M here: the module will be
+         called unioxx5.
+
 config COMEDI_FL512
        tristate "FL512 ISA card support"
        ---help---
@@ -855,14 +872,6 @@ config COMEDI_DYNA_PCI10XX
          To compile this driver as a module, choose M here: the module will be
          called dyna_pci10xx.
 
-config COMEDI_UNIOXX5
-       tristate "Fastwel UNIOxx-5 analog and digital io board support"
-       ---help---
-         Enable support for Fastwel UNIOxx-5 (analog and digital i/o) boards
-
-         To compile this driver as a module, choose M here: the module will be
-         called unioxx5.
-
 config COMEDI_GSC_HPDI
        tristate "General Standards PCI-HPDI32 / PMC-HPDI32 support"
        select COMEDI_FC
@@ -1085,14 +1094,6 @@ config COMEDI_S626
          To compile this driver as a module, choose M here: the module will be
          called s626.
 
-config COMEDI_SSV_DNP
-       tristate "SSV Embedded Systems DIL/Net-PC support"
-       ---help---
-         Enable support for SSV Embedded Systems DIL/Net-PC
-
-         To compile this driver as a module, choose M here: the module will be
-         called ssv_dnp.
-
 config COMEDI_MITE
        depends on HAS_DMA
        tristate
index 3ba4c5712dffe5c9277bab3a0a59933e2b5a7c59..853f62b2b1a982c70ba229f94b4697c9d1e869d3 100644 (file)
@@ -369,28 +369,23 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
 {
        const struct ni_65xx_board *board = comedi_board(dev);
        struct ni_65xx_private *devpriv = dev->private;
-       unsigned base_bitfield_channel;
-       const unsigned max_ports_per_bitfield = 5;
+       int base_bitfield_channel;
        unsigned read_bits = 0;
-       unsigned j;
+       int last_port_offset = ni_65xx_port_by_channel(s->n_chan - 1);
+       int port_offset;
 
        base_bitfield_channel = CR_CHAN(insn->chanspec);
-       for (j = 0; j < max_ports_per_bitfield; ++j) {
-               const unsigned port_offset =
-                       ni_65xx_port_by_channel(base_bitfield_channel) + j;
-               const unsigned port =
-                       sprivate(s)->base_port + port_offset;
-               unsigned base_port_channel;
+       for (port_offset = ni_65xx_port_by_channel(base_bitfield_channel);
+            port_offset <= last_port_offset; port_offset++) {
+               unsigned port = sprivate(s)->base_port + port_offset;
+               int base_port_channel = port_offset * ni_65xx_channels_per_port;
                unsigned port_mask, port_data, port_read_bits;
-               int bitshift;
-               if (port >= ni_65xx_total_num_ports(board))
+               int bitshift = base_port_channel - base_bitfield_channel;
+
+               if (bitshift >= 32)
                        break;
-               base_port_channel = port_offset * ni_65xx_channels_per_port;
                port_mask = data[0];
                port_data = data[1];
-               bitshift = base_port_channel - base_bitfield_channel;
-               if (bitshift >= 32 || bitshift <= -32)
-                       break;
                if (bitshift > 0) {
                        port_mask >>= bitshift;
                        port_data >>= bitshift;
index 724a685753dd8671fba84c9f3e14174164696e64..40ef785a04284d9a4c79633f2877a957b8c405dc 100644 (file)
@@ -474,7 +474,7 @@ static void dgap_cleanup_board(struct board_t *brd)
 
                 DGAP_LOCK(dgap_global_lock, flags);
                 brd->msgbuf = NULL;
-                printk(brd->msgbuf_head);
+                printk("%s", brd->msgbuf_head);
                 kfree(brd->msgbuf_head);
                 brd->msgbuf_head = NULL;
                 DGAP_UNLOCK(dgap_global_lock, flags);
@@ -628,7 +628,7 @@ static int dgap_found_board(struct pci_dev *pdev, int id)
        DPR_INIT(("dgap_scan(%d) - printing out the msgbuf\n", i));
        DGAP_LOCK(dgap_global_lock, flags);
        brd->msgbuf = NULL;
-       printk(brd->msgbuf_head);
+       printk("%s", brd->msgbuf_head);
        kfree(brd->msgbuf_head);
        brd->msgbuf_head = NULL;
        DGAP_UNLOCK(dgap_global_lock, flags);
@@ -955,25 +955,28 @@ static void dgap_mbuf(struct board_t *brd, const char *fmt, ...) {
        char            buf[1024];
        int             i;
        unsigned long   flags;
+       size_t          length;
 
        DGAP_LOCK(dgap_global_lock, flags);
 
        /* Format buf using fmt and arguments contained in ap. */
        va_start(ap, fmt);
-       i = vsprintf(buf, fmt,  ap);
+       i = vsnprintf(buf, sizeof(buf), fmt,  ap);
        va_end(ap);
 
        DPR((buf));
 
        if (!brd || !brd->msgbuf) {
-               printk(buf);
+               printk("%s", buf);
                DGAP_UNLOCK(dgap_global_lock, flags);
                return;
        }
 
-       memcpy(brd->msgbuf, buf, strlen(buf));
-       brd->msgbuf += strlen(buf);
-       *brd->msgbuf = 0;
+       length = strlen(buf) + 1;
+       if (brd->msgbuf - brd->msgbuf_head < length)
+               length = brd->msgbuf - brd->msgbuf_head;
+       memcpy(brd->msgbuf, buf, length);
+       brd->msgbuf += length;
 
        DGAP_UNLOCK(dgap_global_lock, flags);
 }
index f8c1e22585d6cf81f3a4a52262b73608ab68f333..71d2b83cc3a12e365823df2e40fd176ac26120ef 100644 (file)
@@ -454,7 +454,7 @@ static void dgnc_cleanup_board(struct board_t *brd)
 
                DGNC_LOCK(dgnc_global_lock, flags);
                brd->msgbuf = NULL;
-               printk(brd->msgbuf_head);
+               printk("%s", brd->msgbuf_head);
                kfree(brd->msgbuf_head);
                brd->msgbuf_head = NULL;
                DGNC_UNLOCK(dgnc_global_lock, flags);
@@ -710,7 +710,7 @@ static int dgnc_found_board(struct pci_dev *pdev, int id)
        DPR_INIT(("dgnc_scan(%d) - printing out the msgbuf\n", i));
        DGNC_LOCK(dgnc_global_lock, flags);
        brd->msgbuf = NULL;
-       printk(brd->msgbuf_head);
+       printk("%s", brd->msgbuf_head);
        kfree(brd->msgbuf_head);
        brd->msgbuf_head = NULL;
        DGNC_UNLOCK(dgnc_global_lock, flags);
index 44cce2fa6361194a36ac72dff5825575fd324bf5..1d68c49afabea493e6f426f99e7235acc738abbb 100644 (file)
@@ -100,8 +100,9 @@ static int dwc2_driver_probe(struct platform_device *dev)
         */
        if (!dev->dev.dma_mask)
                dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
-       if (!dev->dev.coherent_dma_mask)
-               dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       retval = dma_set_coherent_mask(&dev->dev, DMA_BIT_MASK(32));
+       if (retval)
+               return retval;
 
        irq = platform_get_irq(dev, 0);
        if (irq < 0) {
index f73e58f5ef8d0390f8b4068db2030d9d1b42592c..61da7ee36e458ccd73a634839f5feda5a3d00808 100644 (file)
@@ -4797,21 +4797,8 @@ static int et131x_pci_setup(struct pci_dev *pdev,
        pci_set_master(pdev);
 
        /* Check the DMA addressing support of this device */
-       if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) {
-               rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
-               if (rc < 0) {
-                       dev_err(&pdev->dev,
-                         "Unable to obtain 64 bit DMA for consistent allocations\n");
-                       goto err_release_res;
-               }
-       } else if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
-               rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
-               if (rc < 0) {
-                       dev_err(&pdev->dev,
-                         "Unable to obtain 32 bit DMA for consistent allocations\n");
-                       goto err_release_res;
-               }
-       } else {
+       if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) &&
+           dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) {
                dev_err(&pdev->dev, "No usable DMA addressing method\n");
                rc = -EIO;
                goto err_release_res;
index db4d6dc032432cf0d92ff71d6c38e52dff17ce13..b36feb080cba886f8ebf9a456c519247376dbdcb 100644 (file)
@@ -37,7 +37,7 @@ config IIO_SIMPLE_DUMMY_EVENTS
 
 config IIO_SIMPLE_DUMMY_BUFFER
        boolean "Buffered capture support"
-       depends on IIO_KFIFO_BUF
+       select IIO_KFIFO_BUF
        help
          Add buffered data capture to the simple dummy driver.
 
index 351936c3efd698e8c5cbe76d7878eb8ad16c311f..e4998e4d4434b2af9365aacc1a8c4137a4c70544 100644 (file)
@@ -563,6 +563,7 @@ static int isl29018_probe(struct i2c_client *client,
        mutex_init(&chip->lock);
 
        chip->lux_scale = 1;
+       chip->lux_uscale = 0;
        chip->range = 1000;
        chip->adc_bit = 16;
        chip->suspended = false;
index d2748c329eae6728b9c88c6b3a63065982d78555..c3f3f539e787e926b54f793958d8e9dac13aa6d7 100644 (file)
@@ -229,7 +229,7 @@ static int hmc5843_read_measurement(struct iio_dev *indio_dev,
        if (result < 0)
                return -EINVAL;
 
-       *val = result;
+       *val = sign_extend32(result, 15);
        return IIO_VAL_INT;
 }
 
index a802cf2491d61a6d55f95c6e6825792905fa118a..4c6d2041260bed259f7cba174c64ceb9a9c1a3f8 100644 (file)
@@ -299,7 +299,7 @@ static int ade7854_spi_probe(struct spi_device *spi)
        if (ret)
                iio_device_free(indio_dev);
 
-       return 0;
+       return ret;
 }
 
 static int ade7854_spi_remove(struct spi_device *spi)
index 47c5888461ffbeb3f4aa994af5b2418df6506e60..a475b3e07c9c71481f78214812053d93f62bff83 100644 (file)
@@ -41,7 +41,6 @@ struct imx_drm_device {
        struct list_head                        encoder_list;
        struct list_head                        connector_list;
        struct mutex                            mutex;
-       int                                     references;
        int                                     pipes;
        struct drm_fbdev_cma                    *fbhelper;
 };
@@ -241,8 +240,6 @@ struct drm_device *imx_drm_device_get(void)
                }
        }
 
-       imxdrm->references++;
-
        return imxdrm->drm;
 
 unwind_crtc:
@@ -280,8 +277,6 @@ void imx_drm_device_put(void)
        list_for_each_entry(enc, &imxdrm->encoder_list, list)
                module_put(enc->owner);
 
-       imxdrm->references--;
-
        mutex_unlock(&imxdrm->mutex);
 }
 EXPORT_SYMBOL_GPL(imx_drm_device_put);
@@ -485,7 +480,7 @@ int imx_drm_add_crtc(struct drm_crtc *crtc,
 
        mutex_lock(&imxdrm->mutex);
 
-       if (imxdrm->references) {
+       if (imxdrm->drm->open_count) {
                ret = -EBUSY;
                goto err_busy;
        }
@@ -564,7 +559,7 @@ int imx_drm_add_encoder(struct drm_encoder *encoder,
 
        mutex_lock(&imxdrm->mutex);
 
-       if (imxdrm->references) {
+       if (imxdrm->drm->open_count) {
                ret = -EBUSY;
                goto err_busy;
        }
@@ -709,7 +704,7 @@ int imx_drm_add_connector(struct drm_connector *connector,
 
        mutex_lock(&imxdrm->mutex);
 
-       if (imxdrm->references) {
+       if (imxdrm->drm->open_count) {
                ret = -EBUSY;
                goto err_busy;
        }
@@ -805,6 +800,12 @@ static struct drm_driver imx_drm_driver = {
 
 static int imx_drm_platform_probe(struct platform_device *pdev)
 {
+       int ret;
+
+       ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
+
        imx_drm_device->dev = &pdev->dev;
 
        return drm_platform_init(&imx_drm_driver, pdev);
@@ -847,8 +848,6 @@ static int __init imx_drm_init(void)
                goto err_pdev;
        }
 
-       imx_drm_pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32),
-
        ret = platform_driver_register(&imx_drm_pdrv);
        if (ret)
                goto err_pdrv;
index 6fd37a7453e9691ac573c414d396e69357e7b38f..9e73e8d8c9aaa350267ac25f0926a5cd8d7c6416 100644 (file)
@@ -523,7 +523,9 @@ static int ipu_drm_probe(struct platform_device *pdev)
        if (!pdata)
                return -EINVAL;
 
-       pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        ipu_crtc = devm_kzalloc(&pdev->dev, sizeof(*ipu_crtc), GFP_KERNEL);
        if (!ipu_crtc)
index 2f44d56700af1eabe13625777b3cc3ce8c94cf20..776d3632dc7d52988738b105d648161b2e99b9a2 100644 (file)
@@ -244,13 +244,17 @@ static int snd_toneport_source_put(struct snd_kcontrol *kcontrol,
        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
        struct usb_line6_toneport *toneport =
            (struct usb_line6_toneport *)line6pcm->line6;
+       unsigned int source;
 
-       if (ucontrol->value.enumerated.item[0] == toneport->source)
+       source = ucontrol->value.enumerated.item[0];
+       if (source >= ARRAY_SIZE(toneport_source_info))
+               return -EINVAL;
+       if (source == toneport->source)
                return 0;
 
-       toneport->source = ucontrol->value.enumerated.item[0];
+       toneport->source = source;
        toneport_send_cmd(toneport->line6.usbdev,
-                         toneport_source_info[toneport->source].code, 0x0000);
+                         toneport_source_info[source].code, 0x0000);
        return 1;
 }
 
index 086ca3d7241b2b756a650bc647ab9450461f1a4a..26b49a24b3dfe32997e7d37cb479f2d98b91ce82 100644 (file)
@@ -1802,7 +1802,7 @@ kiblnd_recv (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed,
 int
 kiblnd_thread_start(int (*fn)(void *arg), void *arg, char *name)
 {
-       struct task_struct *task = kthread_run(fn, arg, name);
+       struct task_struct *task = kthread_run(fn, arg, "%s", name);
 
        if (IS_ERR(task))
                return PTR_ERR(task);
index 2c581b7fa8adee363d19791007f4696e9e439d06..68a4f52ec998c14795d6f356e807b798c2dfa794 100644 (file)
@@ -1005,7 +1005,7 @@ ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg)
 int
 ksocknal_thread_start(int (*fn)(void *arg), void *arg, char *name)
 {
-       struct task_struct *task = kthread_run(fn, arg, name);
+       struct task_struct *task = kthread_run(fn, arg, "%s", name);
 
        if (IS_ERR(task))
                return PTR_ERR(task);
index 4e898e4918605bf058554d6cae15b6a5e31e550a..2156a44d07409c0501cba726ccb33ee99d1d9c92 100644 (file)
@@ -1,6 +1,6 @@
 config LUSTRE_FS
        tristate "Lustre file system client support"
-       depends on INET && m
+       depends on INET && m && !MIPS && !XTENSA && !SUPERH
        select LNET
        select CRYPTO
        select CRYPTO_CRC32
@@ -52,7 +52,7 @@ config LUSTRE_DEBUG_EXPENSIVE_CHECK
 config LUSTRE_TRANSLATE_ERRNOS
        bool
        depends on LUSTRE_FS && !X86
-       default true
+       default y
 
 config LUSTRE_LLITE_LLOOP
        bool "Lustre virtual block device"
index 3916bda3004cf23c7fa58c7e51de5e621909cfc5..a100a0b96381d6ef0a55242c969ab41b7adb05be 100644 (file)
@@ -800,9 +800,9 @@ static int ldlm_bl_thread_start(struct ldlm_bl_pool *blp)
 
        init_completion(&bltd.bltd_comp);
        bltd.bltd_num = atomic_read(&blp->blp_num_threads);
-       snprintf(bltd.bltd_name, sizeof(bltd.bltd_name) - 1,
+       snprintf(bltd.bltd_name, sizeof(bltd.bltd_name),
                "ldlm_bl_%02d", bltd.bltd_num);
-       task = kthread_run(ldlm_bl_thread_main, &bltd, bltd.bltd_name);
+       task = kthread_run(ldlm_bl_thread_main, &bltd, "%s", bltd.bltd_name);
        if (IS_ERR(task)) {
                CERROR("cannot start LDLM thread ldlm_bl_%02d: rc %ld\n",
                       atomic_read(&blp->blp_num_threads), PTR_ERR(task));
index 462172d1a7569a74c1ffbae3dd0c0f133574aa2e..1a55c81892e0e8f692c167d17f0296814ad806dc 100644 (file)
@@ -397,7 +397,7 @@ cfs_wi_sched_create(char *name, struct cfs_cpt_table *cptab,
                                 sched->ws_name, sched->ws_nthreads);
                }
 
-               task = kthread_run(cfs_wi_scheduler, sched, name);
+               task = kthread_run(cfs_wi_scheduler, sched, "%s", name);
                if (!IS_ERR(task)) {
                        nthrs--;
                        continue;
index 2644edf438c1e175b016a54e96b6d93bd5852cc7..c8b43442dc74be8c8cf1ee3f5b38470f63617e71 100644 (file)
@@ -1387,7 +1387,7 @@ echo_copyout_lsm (struct lov_stripe_md *lsm, void *_ulsm, int ulsm_nob)
        if (nob > ulsm_nob)
                return (-EINVAL);
 
-       if (copy_to_user (ulsm, lsm, sizeof(ulsm)))
+       if (copy_to_user (ulsm, lsm, sizeof(*ulsm)))
                return (-EFAULT);
 
        for (i = 0; i < lsm->lsm_stripe_count; i++) {
index 227a0ae9593bc987d6bfbcf1757bc0a9eacf2288..5dec771d70eee8c08a6bc0b787f7f116ddd6906d 100644 (file)
@@ -383,8 +383,8 @@ int ptlrpc_start_pinger(void)
 
        /* CLONE_VM and CLONE_FILES just avoid a needless copy, because we
         * just drop the VM and FILES in cfs_daemonize_ctxt() right away. */
-       rc = PTR_ERR(kthread_run(ptlrpc_pinger_main,
-                                &pinger_thread, pinger_thread.t_name));
+       rc = PTR_ERR(kthread_run(ptlrpc_pinger_main, &pinger_thread,
+                                "%s", pinger_thread.t_name));
        if (IS_ERR_VALUE(rc)) {
                CERROR("cannot start thread: %d\n", rc);
                return rc;
index fbdeff65d059df66f057cec95f729a5d3ad6ad63..89c9be96f454a57c4dd0839cf92f378883dce91e 100644 (file)
@@ -615,7 +615,7 @@ int ptlrpcd_start(int index, int max, const char *name, struct ptlrpcd_ctl *pc)
        init_completion(&pc->pc_starting);
        init_completion(&pc->pc_finishing);
        spin_lock_init(&pc->pc_lock);
-       strncpy(pc->pc_name, name, sizeof(pc->pc_name) - 1);
+       strlcpy(pc->pc_name, name, sizeof(pc->pc_name));
        pc->pc_set = ptlrpc_prep_set();
        if (pc->pc_set == NULL)
                GOTO(out, rc = -ENOMEM);
@@ -638,7 +638,7 @@ int ptlrpcd_start(int index, int max, const char *name, struct ptlrpcd_ctl *pc)
                                GOTO(out, rc);
                }
 
-               task = kthread_run(ptlrpcd, pc, pc->pc_name);
+               task = kthread_run(ptlrpcd, pc, "%s", pc->pc_name);
                if (IS_ERR(task))
                        GOTO(out, rc = PTR_ERR(task));
 
@@ -745,7 +745,7 @@ static int ptlrpcd_init(void)
        if (ptlrpcds == NULL)
                GOTO(out, rc = -ENOMEM);
 
-       snprintf(name, 15, "ptlrpcd_rcv");
+       snprintf(name, sizeof(name), "ptlrpcd_rcv");
        set_bit(LIOD_RECOVERY, &ptlrpcds->pd_thread_rcv.pc_flags);
        rc = ptlrpcd_start(-1, nthreads, name, &ptlrpcds->pd_thread_rcv);
        if (rc < 0)
@@ -764,7 +764,7 @@ static int ptlrpcd_init(void)
         *      unnecessary dependency. But how to distribute async RPCs load
         *      among all the ptlrpc daemons becomes another trouble. */
        for (i = 0; i < nthreads; i++) {
-               snprintf(name, 15, "ptlrpcd_%d", i);
+               snprintf(name, sizeof(name), "ptlrpcd_%d", i);
                rc = ptlrpcd_start(i, nthreads, name, &ptlrpcds->pd_threads[i]);
                if (rc < 0)
                        GOTO(out, rc);
index e90c8fb7da6a73643531c1cd1914d5826a280c2d..6547f46a7729f2f95c16f9bdff5e334a43806eea 100644 (file)
@@ -59,8 +59,8 @@
  ****************************************/
 
 
-#define PTRS_PER_PAGE   (PAGE_CACHE_SIZE / sizeof(void *))
-#define PAGES_PER_POOL  (PTRS_PER_PAGE)
+#define POINTERS_PER_PAGE      (PAGE_CACHE_SIZE / sizeof(void *))
+#define PAGES_PER_POOL         (POINTERS_PER_PAGE)
 
 #define IDLE_IDX_MAX       (100)
 #define IDLE_IDX_WEIGHT         (3)
index ac8b5fd2300b5720e322137079895bdda5f71b52..acf75f3873d1ffb0ab9cc4258150b3a9a1b2e3ba 100644 (file)
@@ -2718,15 +2718,15 @@ int ptlrpc_start_thread(struct ptlrpc_service_part *svcpt, int wait)
        spin_unlock(&svcpt->scp_lock);
 
        if (svcpt->scp_cpt >= 0) {
-               snprintf(thread->t_name, PTLRPC_THR_NAME_LEN, "%s%02d_%03d",
+               snprintf(thread->t_name, sizeof(thread->t_name), "%s%02d_%03d",
                         svc->srv_thread_name, svcpt->scp_cpt, thread->t_id);
        } else {
-               snprintf(thread->t_name, PTLRPC_THR_NAME_LEN, "%s_%04d",
+               snprintf(thread->t_name, sizeof(thread->t_name), "%s_%04d",
                         svc->srv_thread_name, thread->t_id);
        }
 
        CDEBUG(D_RPCTRACE, "starting thread '%s'\n", thread->t_name);
-       rc = PTR_ERR(kthread_run(ptlrpc_main, thread, thread->t_name));
+       rc = PTR_ERR(kthread_run(ptlrpc_main, thread, "%s", thread->t_name));
        if (IS_ERR_VALUE(rc)) {
                CERROR("cannot start thread '%s': rc %d\n",
                       thread->t_name, rc);
index 90d6ac46935587fb905e910e39a7a52002888f43..081407be33ab5b6cdec1a01dbfb561bd53056c78 100644 (file)
@@ -901,10 +901,7 @@ dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        int err;
        struct dt3155_priv *pd;
 
-       err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
-       if (err)
-               return -ENODEV;
-       err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+       err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
        if (err)
                return -ENODEV;
        pd = kzalloc(sizeof(*pd), GFP_KERNEL);
index d7b3c82b5ead023bcc4ba85acdd0e307b0eecdc9..45dfe94199ae4ecd951a8142fb6f9140d226942c 100644 (file)
@@ -604,7 +604,7 @@ int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number,
                        }
        }
 
-       memset(usb, 0, sizeof(usb));
+       memset(usb, 0, sizeof(*usb));
        usb->init_flags = flags;
 
        /* Initialize the USB state structure */
index 78b6cb7437695a2f36a3d04adcb338346596b37c..199059d64c9b56796a8a3fb3cf4157ed3ee71ab5 100644 (file)
@@ -48,13 +48,8 @@ static int cvm_oct_fill_hw_skbuff(int pool, int size, int elements)
        while (freed) {
 
                struct sk_buff *skb = dev_alloc_skb(size + 256);
-               if (unlikely(skb == NULL)) {
-                       pr_warning
-                           ("Failed to allocate skb for hardware pool %d\n",
-                            pool);
+               if (unlikely(skb == NULL))
                        break;
-               }
-
                skb_reserve(skb, 256 - (((unsigned long)skb->data) & 0x7f));
                *(struct sk_buff **)(skb->data - sizeof(void *)) = skb;
                cvmx_fpa_free(skb->data, pool, DONT_WRITEBACK(size / 128));
index d8f5f694ec35532055781ff48b6edd79f4e502cd..ea53af30dfa7c619f7d500a8dc3518d648916270 100644 (file)
@@ -373,9 +373,7 @@ int cvm_oct_rgmii_init(struct net_device *dev)
                         * Enable interrupts on inband status changes
                         * for this port.
                         */
-                       gmx_rx_int_en.u64 =
-                           cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
-                                         (index, interface));
+                       gmx_rx_int_en.u64 = 0;
                        gmx_rx_int_en.s.phy_dupx = 1;
                        gmx_rx_int_en.s.phy_link = 1;
                        gmx_rx_int_en.s.phy_spd = 1;
index 34afc16bc4935e35f5e47c12d27925f6fe7c62f3..e14a1bb0436129da4c7f969c4f477063d78da1d9 100644 (file)
@@ -303,6 +303,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
                        if (backlog > budget * cores_in_use && napi != NULL)
                                cvm_oct_enable_one_cpu();
                }
+               rx_count++;
 
                skb_in_hw = USE_SKBUFFS_IN_HW && work->word2.s.bufs == 1;
                if (likely(skb_in_hw)) {
@@ -336,9 +337,6 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
                         */
                        skb = dev_alloc_skb(work->len);
                        if (!skb) {
-                               printk_ratelimited("Port %d failed to allocate "
-                                                  "skbuff, packet dropped\n",
-                                                  work->ipprt);
                                cvm_oct_free_work(work);
                                continue;
                        }
@@ -429,7 +427,6 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget)
 #endif
                                }
                                netif_receive_skb(skb);
-                               rx_count++;
                        } else {
                                /* Drop any packet received for a device that isn't up */
                                /*
index 3605c5da822d953daa6275dda23b675e13b60d5c..6fc77428e83a0c389c51e6cca52ceaa6a8ff7dd9 100644 (file)
@@ -157,8 +157,8 @@ _func_enter_;
 
        *frlen = *frlen + (len + 2);
 
-       return pbuf + len + 2;
 _func_exit_;
+       return pbuf + len + 2;
 }
 
 inline u8 *rtw_set_ie_ch_switch (u8 *buf, u32 *buf_len, u8 ch_switch_mode,
index 8b2ba26ba38d9a44c090167cc9bd862367e92ade..4b2eb8e9b5620ab4529ec9ce8af252ef502a65fc 100644 (file)
@@ -1827,13 +1827,13 @@ unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_fra
 
 #ifdef CONFIG_88EU_P2P
 
-static int get_reg_classes_full_count(struct p2p_channels channel_list)
+static int get_reg_classes_full_count(struct p2p_channels *channel_list)
 {
        int cnt = 0;
        int i;
 
-       for (i = 0; i < channel_list.reg_classes; i++) {
-               cnt += channel_list.reg_class[i].channels;
+       for (i = 0; i < channel_list->reg_classes; i++) {
+               cnt += channel_list->reg_class[i].channels;
        }
 
        return cnt;
@@ -2065,7 +2065,7 @@ void issue_p2p_GO_request(struct adapter *padapter, u8 *raddr)
        /*  + number of channels in all classes */
        len_channellist_attr = 3
           + (1 + 1) * (u16)(pmlmeext->channel_list.reg_classes)
-          + get_reg_classes_full_count(pmlmeext->channel_list);
+          + get_reg_classes_full_count(&pmlmeext->channel_list);
 
        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
        p2pielen += 2;
@@ -2437,7 +2437,7 @@ static void issue_p2p_GO_response(struct adapter *padapter, u8 *raddr, u8 *frame
        /*  + number of channels in all classes */
        len_channellist_attr = 3
           + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
-          + get_reg_classes_full_count(pmlmeext->channel_list);
+          + get_reg_classes_full_count(&pmlmeext->channel_list);
 
        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
 
@@ -2859,7 +2859,7 @@ void issue_p2p_invitation_request(struct adapter *padapter, u8 *raddr)
        /*  + number of channels in all classes */
        len_channellist_attr = 3
           + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
-          + get_reg_classes_full_count(pmlmeext->channel_list);
+          + get_reg_classes_full_count(&pmlmeext->channel_list);
 
        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
 
@@ -3120,7 +3120,7 @@ void issue_p2p_invitation_response(struct adapter *padapter, u8 *raddr, u8 dialo
                /*  + number of channels in all classes */
                len_channellist_attr = 3
                        + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
-                       + get_reg_classes_full_count(pmlmeext->channel_list);
+                       + get_reg_classes_full_count(&pmlmeext->channel_list);
 
                *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
                p2pielen += 2;
index c7ff2e4d1f23fcc4567c747bf97beff945886862..9832dcbbd07fa621467dfc1c216411e627db7e66 100644 (file)
@@ -907,7 +907,7 @@ u32 mp_query_psd(struct adapter *pAdapter, u8 *data)
                sscanf(data, "pts =%d, start =%d, stop =%d", &psd_pts, &psd_start, &psd_stop);
        }
 
-       _rtw_memset(data, '\0', sizeof(data));
+       _rtw_memset(data, '\0', sizeof(*data));
 
        i = psd_start;
        while (i < psd_stop) {
index 013ea487e7acc2e57726b82e6e016d4aebf60b34..8018edd3d42e19fcc0875c7324584d94e6fb02ad 100644 (file)
@@ -631,7 +631,7 @@ void WMMOnAssocRsp(struct adapter *padapter)
        inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
 
        if (pregpriv->wifi_spec == 1) {
-               u32     j, tmp, change_inx;
+               u32     j, tmp, change_inx = false;
 
                /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */
                for (i = 0; i < 4; i++) {
index 9c2e7a20c09ea1ced218d303db5e1213837be751..ec0028d4e61a495cf577efe82fd7bffa0455fbbd 100644 (file)
@@ -57,7 +57,7 @@ static void Init_ODM_ComInfo_88E(struct adapter *Adapter)
        u8 cut_ver, fab_ver;
 
        /*  Init Value */
-       _rtw_memset(dm_odm, 0, sizeof(dm_odm));
+       _rtw_memset(dm_odm, 0, sizeof(*dm_odm));
 
        dm_odm->Adapter = Adapter;
 
index 2bfe72841921bd8fc76ec684130f691e5466e50a..4787bacdcad892da62bf66c05cadb851e090e09d 100644 (file)
@@ -1010,7 +1010,7 @@ enum dm_dig_op {
 #define                DM_false_ALARM_THRESH_LOW       400
 #define                DM_false_ALARM_THRESH_HIGH      1000
 
-#define                DM_DIG_MAX_NIC                  0x3e
+#define                DM_DIG_MAX_NIC                  0x4e
 #define                DM_DIG_MIN_NIC                  0x1e /* 0x22/0x1c */
 
 #define                DM_DIG_MAX_AP                   0x32
index 52b280165a926da8acccb981e539c787c6c422b9..555c801d2ded7e434a5a86335449d5be377796ee 100644 (file)
@@ -188,7 +188,7 @@ enum ChannelPlan {
 
 struct txpowerinfo24g {
        u8 IndexCCK_Base[MAX_RF_PATH][MAX_CHNL_GROUP_24G];
-       u8 IndexBW40_Base[MAX_RF_PATH][MAX_CHNL_GROUP_24G-1];
+       u8 IndexBW40_Base[MAX_RF_PATH][MAX_CHNL_GROUP_24G];
        /* If only one tx, only BW20 and OFDM are used. */
        s8 CCK_Diff[MAX_RF_PATH][MAX_TX_COUNT];
        s8 OFDM_Diff[MAX_RF_PATH][MAX_TX_COUNT];
index a96b018e5e6a3d7208867684983a58ede36c8e82..853ab80a2b860a0a95bfab8d85ba064ca4eef982 100644 (file)
@@ -870,6 +870,7 @@ static struct fwevent wlanevents[] = {
        {0, NULL},
        {0, NULL},
        {0, &rtw_cpwm_event_callback},
+       {0, NULL},
 };
 
 #endif/* _RTL_MLME_EXT_C_ */
index cd4100fb3645ffd1cc2fcb8ec1013c1fa76d30da..95953ebc027922e66ffd3168a965dee33f6a30be 100644 (file)
@@ -6973,7 +6973,7 @@ static int rtw_mp_ctx(struct net_device *dev,
        stop = strncmp(extra, "stop", 4);
        sscanf(extra, "count =%d, pkt", &count);
 
-       _rtw_memset(extra, '\0', sizeof(extra));
+       _rtw_memset(extra, '\0', sizeof(*extra));
 
        if (stop == 0) {
                bStartTest = 0; /*  To set Stop */
index d3078d200e505f4c4f24237eb202d80ae6e9cd69..9ca3180ebaa0e70fbb188c84748971fd4f34922d 100644 (file)
@@ -54,6 +54,7 @@ static struct usb_device_id rtw_usb_id_tbl[] = {
        /*=== Customer ID ===*/
        /****** 8188EUS ********/
        {USB_DEVICE(0x8179, 0x07B8)}, /* Abocom - Abocom */
+       {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
        {}      /* Terminating entry */
 };
 
index 5bc361b16d4ca05e924bd3a326824c852a67b8f0..56144014b7c9ba15126f97b073fb6eea4777937a 100644 (file)
@@ -37,6 +37,8 @@ rt_status SendTxCommandPacket(struct net_device *dev, void *pData, u32 DataLen)
        /* Get TCB and local buffer from common pool.
           (It is shared by CmdQ, MgntQ, and USB coalesce DataQ) */
        skb  = dev_alloc_skb(USB_HWDESC_HEADER_LEN + DataLen + 4);
+       if (!skb)
+               return RT_STATUS_FAILURE;
        memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
        tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
        tcb_desc->queue_index = TXCMD_QUEUE;
index dbf11ecb794ec60dd576578f9f5172d0f4448f10..19d3cf451b880c736c82cce806fdfb14d98b6379 100644 (file)
@@ -172,8 +172,8 @@ static u16 swGetOFDMControlRate(struct vnt_private *pDevice, u16 wRateIdx)
        if (!CARDbIsOFDMinBasicRate(pDevice)) {
                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
                        "swGetOFDMControlRate:(NO OFDM) %d\n", wRateIdx);
-       if (wRateIdx > RATE_24M)
-               wRateIdx = RATE_24M;
+               if (wRateIdx > RATE_24M)
+                       wRateIdx = RATE_24M;
                return wRateIdx;
        }
 
index d0cf7d8a20e5640fe507f3ff1b1dc64c170f9408..8872e0f84f40e825efec5dd7f7614f6c22f43562 100644 (file)
@@ -1634,6 +1634,9 @@ int iwctl_siwencodeext(struct net_device *dev, struct iw_request_info *info,
        if (pMgmt == NULL)
                return -EFAULT;
 
+       if (!(pDevice->flags & DEVICE_FLAGS_OPENED))
+               return -ENODEV;
+
        buf = kzalloc(sizeof(struct viawget_wpa_param), GFP_KERNEL);
        if (buf == NULL)
                return -ENOMEM;
index 536971786ae8e4cb87c27b4705d006df0d5cbee6..6f9d28182445ce99b2d37bcd37aaae3c3d2bdc03 100644 (file)
@@ -1098,6 +1098,8 @@ static int device_close(struct net_device *dev)
     memset(pMgmt->abyCurrBSSID, 0, 6);
     pMgmt->eCurrState = WMAC_STATE_IDLE;
 
+       pDevice->flags &= ~DEVICE_FLAGS_OPENED;
+
     device_free_tx_bufs(pDevice);
     device_free_rx_bufs(pDevice);
     device_free_int_bufs(pDevice);
@@ -1109,7 +1111,6 @@ static int device_close(struct net_device *dev)
     usb_free_urb(pDevice->pInterruptURB);
 
     BSSvClearNodeDBTable(pDevice, 0);
-    pDevice->flags &=(~DEVICE_FLAGS_OPENED);
 
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_close2 \n");
 
index fb743a8811bbc9c0c8c37d23bde37a96b863d735..14f3e852215da5fb27702b4b91687047b9a290c2 100644 (file)
@@ -148,6 +148,8 @@ static void *s_vGetFreeContext(struct vnt_private *pDevice)
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"GetFreeContext()\n");
 
     for (ii = 0; ii < pDevice->cbTD; ii++) {
+       if (!pDevice->apTD[ii])
+               return NULL;
         pContext = pDevice->apTD[ii];
         if (pContext->bBoolInUse == false) {
             pContext->bBoolInUse = true;
index efc56987a60b53a0a409277da639a95b128f5304..7db6f03a00540cd8c2a131ab7039fec6251b72cc 100644 (file)
@@ -2054,7 +2054,7 @@ static int xillybus_init_chrdev(struct xilly_endpoint *endpoint,
                                       NULL,
                                       MKDEV(major, i),
                                       NULL,
-                                      devname);
+                                      "%s", devname);
 
                if (IS_ERR(device)) {
                        pr_warn("xillybus: Failed to create %s "
index 91d94b564433ad2aa3f8b6b5091ca26d03459477..2c4ed52ca849d45b385cbeed0d88a545d4a5fa5d 100644 (file)
@@ -981,4 +981,3 @@ MODULE_PARM_DESC(num_devices, "Number of zram devices");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Nitin Gupta <ngupta@vflare.org>");
 MODULE_DESCRIPTION("Compressed RAM Block Device");
-MODULE_ALIAS("devname:zram");
index 35b61f7d6c6305f79535c3c9e7d8dbbd8bd788dc..38e44b9abf0f145eacde1e9b90dcf26c45ca2633 100644 (file)
@@ -753,7 +753,8 @@ static void iscsit_unmap_iovec(struct iscsi_cmd *cmd)
 
 static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
 {
-       struct iscsi_cmd *cmd;
+       LIST_HEAD(ack_list);
+       struct iscsi_cmd *cmd, *cmd_p;
 
        conn->exp_statsn = exp_statsn;
 
@@ -761,19 +762,23 @@ static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
                return;
 
        spin_lock_bh(&conn->cmd_lock);
-       list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
+       list_for_each_entry_safe(cmd, cmd_p, &conn->conn_cmd_list, i_conn_node) {
                spin_lock(&cmd->istate_lock);
                if ((cmd->i_state == ISTATE_SENT_STATUS) &&
                    iscsi_sna_lt(cmd->stat_sn, exp_statsn)) {
                        cmd->i_state = ISTATE_REMOVE;
                        spin_unlock(&cmd->istate_lock);
-                       iscsit_add_cmd_to_immediate_queue(cmd, conn,
-                                               cmd->i_state);
+                       list_move_tail(&cmd->i_conn_node, &ack_list);
                        continue;
                }
                spin_unlock(&cmd->istate_lock);
        }
        spin_unlock_bh(&conn->cmd_lock);
+
+       list_for_each_entry_safe(cmd, cmd_p, &ack_list, i_conn_node) {
+               list_del(&cmd->i_conn_node);
+               iscsit_free_cmd(cmd, false);
+       }
 }
 
 static int iscsit_allocate_iovecs(struct iscsi_cmd *cmd)
index 14d1aed5af1dbef98aa9b05ad31573b08bdf72ed..ef6d836a4d09745d57ba42e2496dd725f85c57ea 100644 (file)
@@ -1192,7 +1192,7 @@ get_target:
         */
 alloc_tags:
        tag_num = max_t(u32, ISCSIT_MIN_TAGS, queue_depth);
-       tag_num += ISCSIT_EXTRA_TAGS;
+       tag_num += (tag_num / 2) + ISCSIT_EXTRA_TAGS;
        tag_size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size;
 
        ret = transport_alloc_session_tags(sess->se_sess, tag_num, tag_size);
index f2de28e178fd738cd93dce94ad7980422749f9d2..b0cac0c342e1e83a9da5dc7b5f01edd48cb12136 100644 (file)
@@ -736,7 +736,7 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown)
                 * Fallthrough
                 */
        case ISCSI_OP_SCSI_TMFUNC:
-               rc = transport_generic_free_cmd(&cmd->se_cmd, 1);
+               rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown);
                if (!rc && shutdown && se_cmd && se_cmd->se_sess) {
                        __iscsit_free_cmd(cmd, true, shutdown);
                        target_put_sess_cmd(se_cmd->se_sess, se_cmd);
@@ -752,7 +752,7 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown)
                        se_cmd = &cmd->se_cmd;
                        __iscsit_free_cmd(cmd, true, shutdown);
 
-                       rc = transport_generic_free_cmd(&cmd->se_cmd, 1);
+                       rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown);
                        if (!rc && shutdown && se_cmd->se_sess) {
                                __iscsit_free_cmd(cmd, true, shutdown);
                                target_put_sess_cmd(se_cmd->se_sess, se_cmd);
index 6c17295e8d7ca9db7a0d262a087ce81ffaa1091c..4714c6f8da4be5fe39e797237fa8a35de0450883 100644 (file)
@@ -349,7 +349,16 @@ static sense_reason_t compare_and_write_post(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
 
-       cmd->se_cmd_flags |= SCF_COMPARE_AND_WRITE_POST;
+       /*
+        * Only set SCF_COMPARE_AND_WRITE_POST to force a response fall-through
+        * within target_complete_ok_work() if the command was successfully
+        * sent to the backend driver.
+        */
+       spin_lock_irq(&cmd->t_state_lock);
+       if ((cmd->transport_state & CMD_T_SENT) && !cmd->scsi_status)
+               cmd->se_cmd_flags |= SCF_COMPARE_AND_WRITE_POST;
+       spin_unlock_irq(&cmd->t_state_lock);
+
        /*
         * Unlock ->caw_sem originally obtained during sbc_compare_and_write()
         * before the original READ I/O submission.
@@ -363,7 +372,7 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
        struct scatterlist *write_sg = NULL, *sg;
-       unsigned char *buf, *addr;
+       unsigned char *buf = NULL, *addr;
        struct sg_mapping_iter m;
        unsigned int offset = 0, len;
        unsigned int nlbas = cmd->t_task_nolb;
@@ -378,6 +387,15 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd)
         */
        if (!cmd->t_data_sg || !cmd->t_bidi_data_sg)
                return TCM_NO_SENSE;
+       /*
+        * Immediately exit + release dev->caw_sem if command has already
+        * been failed with a non-zero SCSI status.
+        */
+       if (cmd->scsi_status) {
+               pr_err("compare_and_write_callback: non zero scsi_status:"
+                       " 0x%02x\n", cmd->scsi_status);
+               goto out;
+       }
 
        buf = kzalloc(cmd->data_length, GFP_KERNEL);
        if (!buf) {
@@ -508,6 +526,12 @@ sbc_compare_and_write(struct se_cmd *cmd)
                cmd->transport_complete_callback = NULL;
                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
        }
+       /*
+        * Reset cmd->data_length to individual block_size in order to not
+        * confuse backend drivers that depend on this value matching the
+        * size of the I/O being submitted.
+        */
+       cmd->data_length = cmd->t_task_nolb * dev->dev_attrib.block_size;
 
        ret = cmd->execute_rw(cmd, cmd->t_bidi_data_sg, cmd->t_bidi_data_nents,
                              DMA_FROM_DEVICE);
index 84747cc1aac0aa4d001dda34bc22d09c52685362..81e945eefbbdd0572181d84e3cd9d014895e4eb7 100644 (file)
@@ -236,17 +236,24 @@ int transport_alloc_session_tags(struct se_session *se_sess,
 {
        int rc;
 
-       se_sess->sess_cmd_map = kzalloc(tag_num * tag_size, GFP_KERNEL);
+       se_sess->sess_cmd_map = kzalloc(tag_num * tag_size,
+                                       GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
        if (!se_sess->sess_cmd_map) {
-               pr_err("Unable to allocate se_sess->sess_cmd_map\n");
-               return -ENOMEM;
+               se_sess->sess_cmd_map = vzalloc(tag_num * tag_size);
+               if (!se_sess->sess_cmd_map) {
+                       pr_err("Unable to allocate se_sess->sess_cmd_map\n");
+                       return -ENOMEM;
+               }
        }
 
        rc = percpu_ida_init(&se_sess->sess_tag_pool, tag_num);
        if (rc < 0) {
                pr_err("Unable to init se_sess->sess_tag_pool,"
                        " tag_num: %u\n", tag_num);
-               kfree(se_sess->sess_cmd_map);
+               if (is_vmalloc_addr(se_sess->sess_cmd_map))
+                       vfree(se_sess->sess_cmd_map);
+               else
+                       kfree(se_sess->sess_cmd_map);
                se_sess->sess_cmd_map = NULL;
                return -ENOMEM;
        }
@@ -412,7 +419,10 @@ void transport_free_session(struct se_session *se_sess)
 {
        if (se_sess->sess_cmd_map) {
                percpu_ida_destroy(&se_sess->sess_tag_pool);
-               kfree(se_sess->sess_cmd_map);
+               if (is_vmalloc_addr(se_sess->sess_cmd_map))
+                       vfree(se_sess->sess_cmd_map);
+               else
+                       kfree(se_sess->sess_cmd_map);
        }
        kmem_cache_free(se_sess_cache, se_sess);
 }
index 4d22e7d2adcae0a048684613c3b3dc95c6f9874e..3da4fd10b9f820b6409980055ae19a2b3607f713 100644 (file)
@@ -298,8 +298,8 @@ static int target_xcopy_parse_segdesc_02(struct se_cmd *se_cmd, struct xcopy_op
                (unsigned long long)xop->dst_lba);
 
        if (dc != 0) {
-               xop->dbl = (desc[29] << 16) & 0xff;
-               xop->dbl |= (desc[30] << 8) & 0xff;
+               xop->dbl = (desc[29] & 0xff) << 16;
+               xop->dbl |= (desc[30] & 0xff) << 8;
                xop->dbl |= desc[31] & 0xff;
 
                pr_debug("XCOPY seg desc 0x02: DC=1 w/ dbl: %u\n", xop->dbl);
index e61c36cbb866474841f9bdf92d934d3c5ece137a..c193af6a628f45758a7fcd59b1b0823e57327655 100644 (file)
@@ -636,6 +636,7 @@ struct console xenboot_console = {
        .name           = "xenboot",
        .write          = xenboot_write_console,
        .flags          = CON_PRINTBUFFER | CON_BOOT | CON_ANYTIME,
+       .index          = -1,
 };
 #endif /* CONFIG_EARLY_PRINTK */
 
index c9a9ddd1d0bc2aa5091d7e1678920df2d9292429..7a744b69c3d144516388d3e8a4bc2fc440fd4d34 100644 (file)
@@ -1758,8 +1758,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
                canon_change = (old->c_lflag ^ tty->termios.c_lflag) & ICANON;
        if (canon_change) {
                bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
-               ldata->line_start = 0;
-               ldata->canon_head = ldata->read_tail;
+               ldata->line_start = ldata->canon_head = ldata->read_tail;
                ldata->erasing = 0;
                ldata->lnext = 0;
        }
@@ -2184,28 +2183,34 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
 
                if (!input_available_p(tty, 0)) {
                        if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
-                               retval = -EIO;
-                               break;
-                       }
-                       if (tty_hung_up_p(file))
-                               break;
-                       if (!timeout)
-                               break;
-                       if (file->f_flags & O_NONBLOCK) {
-                               retval = -EAGAIN;
-                               break;
-                       }
-                       if (signal_pending(current)) {
-                               retval = -ERESTARTSYS;
-                               break;
-                       }
-                       n_tty_set_room(tty);
-                       up_read(&tty->termios_rwsem);
+                               up_read(&tty->termios_rwsem);
+                               tty_flush_to_ldisc(tty);
+                               down_read(&tty->termios_rwsem);
+                               if (!input_available_p(tty, 0)) {
+                                       retval = -EIO;
+                                       break;
+                               }
+                       } else {
+                               if (tty_hung_up_p(file))
+                                       break;
+                               if (!timeout)
+                                       break;
+                               if (file->f_flags & O_NONBLOCK) {
+                                       retval = -EAGAIN;
+                                       break;
+                               }
+                               if (signal_pending(current)) {
+                                       retval = -ERESTARTSYS;
+                                       break;
+                               }
+                               n_tty_set_room(tty);
+                               up_read(&tty->termios_rwsem);
 
-                       timeout = schedule_timeout(timeout);
+                               timeout = schedule_timeout(timeout);
 
-                       down_read(&tty->termios_rwsem);
-                       continue;
+                               down_read(&tty->termios_rwsem);
+                               continue;
+                       }
                }
                __set_current_state(TASK_RUNNING);
 
index 52379e56a31e7abc43a6642a799b1be7744be6c8..44077c0b7670075625650c9d00cc98a63bb90f5c 100644 (file)
@@ -667,30 +667,21 @@ static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf)
 
 static int dma_push_rx(struct eg20t_port *priv, int size)
 {
-       struct tty_struct *tty;
        int room;
        struct uart_port *port = &priv->port;
        struct tty_port *tport = &port->state->port;
 
-       port = &priv->port;
-       tty = tty_port_tty_get(tport);
-       if (!tty) {
-               dev_dbg(priv->port.dev, "%s:tty is busy now", __func__);
-               return 0;
-       }
-
        room = tty_buffer_request_room(tport, size);
 
        if (room < size)
                dev_warn(port->dev, "Rx overrun: dropping %u bytes\n",
                         size - room);
        if (!room)
-               return room;
+               return 0;
 
        tty_insert_flip_string(tport, sg_virt(&priv->sg_rx), size);
 
        port->icount.rx += room;
-       tty_kref_put(tty);
 
        return room;
 }
@@ -1098,6 +1089,8 @@ static void pch_uart_err_ir(struct eg20t_port *priv, unsigned int lsr)
        if (tty == NULL) {
                for (i = 0; error_msg[i] != NULL; i++)
                        dev_err(&priv->pdev->dev, error_msg[i]);
+       } else {
+               tty_kref_put(tty);
        }
 }
 
index d0d972f7e43e3759fb03119786a1103764c86730..0489a2bdcdf9a1aff4af5dacd1d7766f9671a523 100644 (file)
@@ -732,7 +732,7 @@ static irqreturn_t tegra_uart_isr(int irq, void *data)
 static void tegra_uart_stop_rx(struct uart_port *u)
 {
        struct tegra_uart_port *tup = to_tegra_uport(u);
-       struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port);
+       struct tty_struct *tty;
        struct tty_port *port = &u->state->port;
        struct dma_tx_state state;
        unsigned long ier;
@@ -744,6 +744,8 @@ static void tegra_uart_stop_rx(struct uart_port *u)
        if (!tup->rx_in_progress)
                return;
 
+       tty = tty_port_tty_get(&tup->uport.state->port);
+
        tegra_uart_wait_sym_time(tup, 1); /* wait a character interval */
 
        ier = tup->ier_shadow;
index a9355ce1c6d586cef3c9cd62641a141bfa91c245..3a1a01af9a805b38b05f1833eefa80400072f4f4 100644 (file)
@@ -854,7 +854,8 @@ void disassociate_ctty(int on_exit)
                        struct pid *tty_pgrp = tty_get_pgrp(tty);
                        if (tty_pgrp) {
                                kill_pgrp(tty_pgrp, SIGHUP, on_exit);
-                               kill_pgrp(tty_pgrp, SIGCONT, on_exit);
+                               if (!on_exit)
+                                       kill_pgrp(tty_pgrp, SIGCONT, on_exit);
                                put_pid(tty_pgrp);
                        }
                }
index 03ba081c577251a0947466b79f23b36b359b51c1..6fd60fece6b4b01684695b7df4af376e695ff873 100644 (file)
@@ -1201,6 +1201,9 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
                }
                return 0;
        case TCFLSH:
+               retval = tty_check_change(tty);
+               if (retval)
+                       return retval;
                return __tty_perform_flush(tty, arg);
        default:
                /* Try the mode commands */
index 4a851e15e58cdfb6832fbc14c93e3e96cb6f9515..77b47d82c9a69d05d7985068fb956f961b6481f1 100644 (file)
@@ -1,6 +1,6 @@
 config USB_CHIPIDEA
        tristate "ChipIdea Highspeed Dual Role Controller"
-       depends on (USB_EHCI_HCD && USB_GADGET) || (USB_EHCI_HCD && !USB_GADGET) || (!USB_EHCI_HCD && USB_GADGET)
+       depends on ((USB_EHCI_HCD && USB_GADGET) || (USB_EHCI_HCD && !USB_GADGET) || (!USB_EHCI_HCD && USB_GADGET)) && HAS_DMA
        help
          Say Y here if your system has a dual role high speed USB
          controller based on ChipIdea silicon IP. Currently, only the
index 74d998d9b45b28001e2f15f6026640ecb6e07085..7ad541591c81c0db06b6dc6b4b3d7e6d49137103 100644 (file)
@@ -121,17 +121,16 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 
        pdata.phy = data->phy;
 
-       if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
-       if (!pdev->dev.coherent_dma_mask)
-               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               goto err_clk;
 
        if (data->usbmisc_data) {
                ret = imx_usbmisc_init(data->usbmisc_data);
                if (ret) {
                        dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n",
                                        ret);
-                       goto err_clk;
+                       goto err_phy;
                }
        }
 
@@ -143,7 +142,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
                dev_err(&pdev->dev,
                        "Can't register ci_hdrc platform device, err=%d\n",
                        ret);
-               goto err_clk;
+               goto err_phy;
        }
 
        if (data->usbmisc_data) {
@@ -164,6 +163,9 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
 
 disable_device:
        ci_hdrc_remove_device(data->ci_pdev);
+err_phy:
+       if (data->phy)
+               usb_phy_shutdown(data->phy);
 err_clk:
        clk_disable_unprepare(data->clk);
        return ret;
index 042320a6c6c79278ac27191980c0fb63f7ddfc35..d514332ac0811c9fec55a40253b3c526d19cde6d 100644 (file)
@@ -129,7 +129,12 @@ static DEFINE_PCI_DEVICE_TABLE(ci_hdrc_pci_id_table) = {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0829),
                .driver_data = (kernel_ulong_t)&penwell_pci_platdata,
        },
-       { 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ }
+       {
+               /* Intel Clovertrail */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe006),
+               .driver_data = (kernel_ulong_t)&penwell_pci_platdata,
+       },
+       { 0 } /* end: all zeroes */
 };
 MODULE_DEVICE_TABLE(pci, ci_hdrc_pci_id_table);
 
index 94626409559a96a79c0d027023dbade8a645ce58..23763dcec069b2e8d1ba6dd140fc9cf644d2ddec 100644 (file)
@@ -605,6 +605,7 @@ static int ci_hdrc_remove(struct platform_device *pdev)
        dbg_remove_files(ci);
        free_irq(ci->irq, ci);
        ci_role_destroy(ci);
+       kfree(ci->hw_bank.regmap);
 
        return 0;
 }
index 6b4c2f2eb94649c7da6fc577b54598d53ebdfec4..9333083dd1111c047c7016a44402242e2aa87f7d 100644 (file)
@@ -1600,6 +1600,8 @@ static void destroy_eps(struct ci_hdrc *ci)
        for (i = 0; i < ci->hw_ep_max; i++) {
                struct ci_hw_ep *hwep = &ci->ci_hw_ep[i];
 
+               if (hwep->pending_td)
+                       free_pending_td(hwep);
                dma_pool_free(ci->qh_pool, hwep->qh.ptr, hwep->qh.dma);
        }
 }
@@ -1667,13 +1669,13 @@ static int ci_udc_stop(struct usb_gadget *gadget,
                if (ci->platdata->notify_event)
                        ci->platdata->notify_event(ci,
                        CI_HDRC_CONTROLLER_STOPPED_EVENT);
-               ci->driver = NULL;
                spin_unlock_irqrestore(&ci->lock, flags);
                _gadget_stop_activity(&ci->gadget);
                spin_lock_irqsave(&ci->lock, flags);
                pm_runtime_put(&ci->gadget.dev);
        }
 
+       ci->driver = NULL;
        spin_unlock_irqrestore(&ci->lock, flags);
 
        return 0;
index 737e3c19967bee3e81f57cc041ec9989ec38fb57..71dc5d768fa5cef3edc5ac27c84c032d2a0a0dcf 100644 (file)
@@ -742,6 +742,22 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,
                if ((index & ~USB_DIR_IN) == 0)
                        return 0;
                ret = findintfep(ps->dev, index);
+               if (ret < 0) {
+                       /*
+                        * Some not fully compliant Win apps seem to get
+                        * index wrong and have the endpoint number here
+                        * rather than the endpoint address (with the
+                        * correct direction). Win does let this through,
+                        * so we'll not reject it here but leave it to
+                        * the device to not break KVM. But we warn.
+                        */
+                       ret = findintfep(ps->dev, index ^ 0x80);
+                       if (ret >= 0)
+                               dev_info(&ps->dev->dev,
+                                       "%s: process %i (%s) requesting ep %02x but needs %02x\n",
+                                       __func__, task_pid_nr(current),
+                                       current->comm, index, index ^ 0x80);
+               }
                if (ret >= 0)
                        ret = checkintf(ps, ret);
                break;
index dde4c83516a1870bd4ed7a11e3fe433ced0979af..e6b682c6c236b8152561496b2e00bba22e75e25c 100644 (file)
@@ -3426,6 +3426,9 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state)
        unsigned long long u2_pel;
        int ret;
 
+       if (udev->state != USB_STATE_CONFIGURED)
+               return 0;
+
        /* Convert SEL and PEL stored in ns to us */
        u1_sel = DIV_ROUND_UP(udev->u1_params.sel, 1000);
        u1_pel = DIV_ROUND_UP(udev->u1_params.pel, 1000);
index b870872e020f1e0bd8e93c157b76d145bc2b2122..70fc43027a5c65b6f29f22dc9ec64c18db220323 100644 (file)
@@ -1,7 +1,6 @@
 config USB_DWC3
        tristate "DesignWare USB3 DRD Core Support"
        depends on (USB || USB_GADGET) && HAS_DMA
-       depends on EXTCON
        select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
        help
          Say Y or M here if your system has a Dual Role SuperSpeed
index 2f2e88a3a11a3c9a9adbcca6b104b54fa2f4352b..8b20c70d91e788c8e27791b98e454c4a5ba87ae7 100644 (file)
@@ -119,10 +119,9 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
         * Since shared usb code relies on it, set it here for now.
         * Once we move to full device tree support this will vanish off.
         */
-       if (!dev->dma_mask)
-               dev->dma_mask = &dev->coherent_dma_mask;
-       if (!dev->coherent_dma_mask)
-               dev->coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
+       if (ret)
+               goto err1;
 
        platform_set_drvdata(pdev, exynos);
 
index 9b138129e856aa22b27c4a83398adf55c8949247..2e252aae51ca0bcc5da41b3251c45cec91cced7d 100644 (file)
@@ -28,6 +28,8 @@
 /* FIXME define these in <linux/pci_ids.h> */
 #define PCI_VENDOR_ID_SYNOPSYS         0x16c3
 #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3        0xabcd
+#define PCI_DEVICE_ID_INTEL_BYT                0x0f37
+#define PCI_DEVICE_ID_INTEL_MRFLD      0x119e
 
 struct dwc3_pci {
        struct device           *dev;
@@ -187,6 +189,8 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {
                PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
                                PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3),
        },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
        {  }    /* Terminating Entry */
 };
 MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
index f168eaebdef8fc6731de7c6994c658737495fdce..5452c0fce36074d4238e3553bb00d879d8df9ac3 100644 (file)
@@ -2611,15 +2611,13 @@ int dwc3_gadget_init(struct dwc3 *dwc)
        ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
        if (ret) {
                dev_err(dwc->dev, "failed to register udc\n");
-               goto err5;
+               goto err4;
        }
 
        return 0;
 
-err5:
-       dwc3_gadget_free_endpoints(dwc);
-
 err4:
+       dwc3_gadget_free_endpoints(dwc);
        dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
                        dwc->ep0_bounce, dwc->ep0_bounce_addr);
 
index 5a5acf22c694514f5b3ebede7903f9912e4138b5..e126b6b248e63cd1b412bea2561e90bd15a104d3 100644 (file)
@@ -113,12 +113,6 @@ static int __init cdc_do_config(struct usb_configuration *c)
                c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
        }
 
-       fi_ecm = usb_get_function_instance("ecm");
-       if (IS_ERR(fi_ecm)) {
-               status = PTR_ERR(fi_ecm);
-               goto err_func_ecm;
-       }
-
        f_ecm = usb_get_function(fi_ecm);
        if (IS_ERR(f_ecm)) {
                status = PTR_ERR(f_ecm);
@@ -129,35 +123,24 @@ static int __init cdc_do_config(struct usb_configuration *c)
        if (status)
                goto err_add_ecm;
 
-       fi_serial = usb_get_function_instance("acm");
-       if (IS_ERR(fi_serial)) {
-               status = PTR_ERR(fi_serial);
-               goto err_get_acm;
-       }
-
        f_acm = usb_get_function(fi_serial);
        if (IS_ERR(f_acm)) {
                status = PTR_ERR(f_acm);
-               goto err_func_acm;
+               goto err_get_acm;
        }
 
        status = usb_add_function(c, f_acm);
        if (status)
                goto err_add_acm;
-
        return 0;
 
 err_add_acm:
        usb_put_function(f_acm);
-err_func_acm:
-       usb_put_function_instance(fi_serial);
 err_get_acm:
        usb_remove_function(c, f_ecm);
 err_add_ecm:
        usb_put_function(f_ecm);
 err_get_ecm:
-       usb_put_function_instance(fi_ecm);
-err_func_ecm:
        return status;
 }
 
index 06ecd08fd57a3174022a3579f458c84f30440123..b8a2376971a47aa357794117f74390aaee01a594 100644 (file)
@@ -923,8 +923,9 @@ static int dummy_udc_stop(struct usb_gadget *g,
        struct dummy_hcd        *dum_hcd = gadget_to_dummy_hcd(g);
        struct dummy            *dum = dum_hcd->dum;
 
-       dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
-                       driver->driver.name);
+       if (driver)
+               dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
+                               driver->driver.name);
 
        dum->driver = NULL;
 
@@ -1000,8 +1001,8 @@ static int dummy_udc_remove(struct platform_device *pdev)
 {
        struct dummy    *dum = platform_get_drvdata(pdev);
 
-       usb_del_gadget_udc(&dum->gadget);
        device_remove_file(&dum->gadget.dev, &dev_attr_function);
+       usb_del_gadget_udc(&dum->gadget);
        return 0;
 }
 
index edab45da37417e16960b75033a46a8453475b77b..8d9e6f7e8f1a5a6c36965dfdd4c5a213f4f917aa 100644 (file)
@@ -995,7 +995,7 @@ static void ecm_unbind(struct usb_configuration *c, struct usb_function *f)
        usb_ep_free_request(ecm->notify, ecm->notify_req);
 }
 
-struct usb_function *ecm_alloc(struct usb_function_instance *fi)
+static struct usb_function *ecm_alloc(struct usb_function_instance *fi)
 {
        struct f_ecm    *ecm;
        struct f_ecm_opts *opts;
index d00392d879db3aa3e75d093d4e26041fa42bcb54..d61c11d765d0a92b9e9e79270e9de4b3cb474ca3 100644 (file)
@@ -624,7 +624,7 @@ static void eem_unbind(struct usb_configuration *c, struct usb_function *f)
        usb_free_all_descriptors(f);
 }
 
-struct usb_function *eem_alloc(struct usb_function_instance *fi)
+static struct usb_function *eem_alloc(struct usb_function_instance *fi)
 {
        struct f_eem    *eem;
        struct f_eem_opts *opts;
index 1a66c5baa0d1f292188a1756cf17d5243b2ffe58..44cf775a86271ccd95cdf9577c283fc899e70d6c 100644 (file)
@@ -1034,37 +1034,19 @@ struct ffs_sb_fill_data {
        struct ffs_file_perms perms;
        umode_t root_mode;
        const char *dev_name;
-       union {
-               /* set by ffs_fs_mount(), read by ffs_sb_fill() */
-               void *private_data;
-               /* set by ffs_sb_fill(), read by ffs_fs_mount */
-               struct ffs_data *ffs_data;
-       };
+       struct ffs_data *ffs_data;
 };
 
 static int ffs_sb_fill(struct super_block *sb, void *_data, int silent)
 {
        struct ffs_sb_fill_data *data = _data;
        struct inode    *inode;
-       struct ffs_data *ffs;
+       struct ffs_data *ffs = data->ffs_data;
 
        ENTER();
 
-       /* Initialise data */
-       ffs = ffs_data_new();
-       if (unlikely(!ffs))
-               goto Enomem;
-
        ffs->sb              = sb;
-       ffs->dev_name        = kstrdup(data->dev_name, GFP_KERNEL);
-       if (unlikely(!ffs->dev_name))
-               goto Enomem;
-       ffs->file_perms      = data->perms;
-       ffs->private_data    = data->private_data;
-
-       /* used by the caller of this function */
-       data->ffs_data       = ffs;
-
+       data->ffs_data       = NULL;
        sb->s_fs_info        = ffs;
        sb->s_blocksize      = PAGE_CACHE_SIZE;
        sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
@@ -1080,17 +1062,14 @@ static int ffs_sb_fill(struct super_block *sb, void *_data, int silent)
                                  &data->perms);
        sb->s_root = d_make_root(inode);
        if (unlikely(!sb->s_root))
-               goto Enomem;
+               return -ENOMEM;
 
        /* EP0 file */
        if (unlikely(!ffs_sb_create_file(sb, "ep0", ffs,
                                         &ffs_ep0_operations, NULL)))
-               goto Enomem;
+               return -ENOMEM;
 
        return 0;
-
-Enomem:
-       return -ENOMEM;
 }
 
 static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts)
@@ -1193,6 +1172,7 @@ ffs_fs_mount(struct file_system_type *t, int flags,
        struct dentry *rv;
        int ret;
        void *ffs_dev;
+       struct ffs_data *ffs;
 
        ENTER();
 
@@ -1200,18 +1180,30 @@ ffs_fs_mount(struct file_system_type *t, int flags,
        if (unlikely(ret < 0))
                return ERR_PTR(ret);
 
+       ffs = ffs_data_new();
+       if (unlikely(!ffs))
+               return ERR_PTR(-ENOMEM);
+       ffs->file_perms = data.perms;
+
+       ffs->dev_name = kstrdup(dev_name, GFP_KERNEL);
+       if (unlikely(!ffs->dev_name)) {
+               ffs_data_put(ffs);
+               return ERR_PTR(-ENOMEM);
+       }
+
        ffs_dev = functionfs_acquire_dev_callback(dev_name);
-       if (IS_ERR(ffs_dev))
-               return ffs_dev;
+       if (IS_ERR(ffs_dev)) {
+               ffs_data_put(ffs);
+               return ERR_CAST(ffs_dev);
+       }
+       ffs->private_data = ffs_dev;
+       data.ffs_data = ffs;
 
-       data.dev_name = dev_name;
-       data.private_data = ffs_dev;
        rv = mount_nodev(t, flags, &data, ffs_sb_fill);
-
-       /* data.ffs_data is set by ffs_sb_fill */
-       if (IS_ERR(rv))
+       if (IS_ERR(rv) && data.ffs_data) {
                functionfs_release_dev_callback(data.ffs_data);
-
+               ffs_data_put(data.ffs_data);
+       }
        return rv;
 }
 
@@ -2264,6 +2256,8 @@ static int ffs_func_bind(struct usb_configuration *c,
                                   data->raw_descs + ret,
                                   (sizeof data->raw_descs) - ret,
                                   __ffs_func_bind_do_descs, func);
+               if (unlikely(ret < 0))
+                       goto error;
        }
 
        /*
index 313b835eedfd58948d23a96a85ade673347e8114..a01d7d38c01685135a503885342be7f9ec63ebbd 100644 (file)
@@ -2260,10 +2260,12 @@ reset:
                /* Disable the endpoints */
                if (fsg->bulk_in_enabled) {
                        usb_ep_disable(fsg->bulk_in);
+                       fsg->bulk_in->driver_data = NULL;
                        fsg->bulk_in_enabled = 0;
                }
                if (fsg->bulk_out_enabled) {
                        usb_ep_disable(fsg->bulk_out);
+                       fsg->bulk_out->driver_data = NULL;
                        fsg->bulk_out_enabled = 0;
                }
 
index 32db2eee2d8738fe5388f8c00bd2c644ac2b5b20..bbbfd19487784c6ebbfb107a24a7233c45740a45 100644 (file)
@@ -1214,6 +1214,6 @@ static struct platform_driver fotg210_driver = {
 
 module_platform_driver(fotg210_driver);
 
-MODULE_AUTHOR("Yuan-Hsin Chen <yhchen@faraday-tech.com>");
+MODULE_AUTHOR("Yuan-Hsin Chen, Feng-Hsin Chiang <john453@faraday-tech.com>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION(DRIVER_DESC);
index f1dd6daabe217c0742140c1619c3be5aa22c8c54..b278abe524539640f14a29f70a1f3a9d25fa1747 100644 (file)
@@ -22,7 +22,7 @@
 
 MODULE_DESCRIPTION("FUSB300  USB gadget driver");
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Yuan Hsin Chen <yhchen@faraday-tech.com>");
+MODULE_AUTHOR("Yuan-Hsin Chen, Feng-Hsin Chiang <john453@faraday-tech.com>");
 MODULE_ALIAS("platform:fusb300_udc");
 
 #define DRIVER_VERSION "20 October 2010"
index 67128be1e1b70f25b29f8cc571b1b916a9c35f2c..6a2a65aa0057c9d822cd5d9bac61aaeac470bd71 100644 (file)
@@ -3078,7 +3078,9 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
                 udc->isp1301_i2c_client->addr);
 
        pdev->dev.dma_mask = &lpc32xx_usbd_dmamask;
-       pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       retval = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+       if (retval)
+               goto resource_fail;
 
        udc->board = &lpc32xx_usbddata;
 
index 2a1ebefd8f9eb31318fc861fbc010214148db18d..23393254a8a35593526062cc09880f50c809dced 100644 (file)
@@ -179,7 +179,7 @@ err_conf:
        return ret;
 }
 
-static int rndis_config_register(struct usb_composite_dev *cdev)
+static __ref int rndis_config_register(struct usb_composite_dev *cdev)
 {
        static struct usb_configuration config = {
                .bConfigurationValue    = MULTI_RNDIS_CONFIG_NUM,
@@ -194,7 +194,7 @@ static int rndis_config_register(struct usb_composite_dev *cdev)
 
 #else
 
-static int rndis_config_register(struct usb_composite_dev *cdev)
+static __ref int rndis_config_register(struct usb_composite_dev *cdev)
 {
        return 0;
 }
@@ -241,7 +241,7 @@ err_conf:
        return ret;
 }
 
-static int cdc_config_register(struct usb_composite_dev *cdev)
+static __ref int cdc_config_register(struct usb_composite_dev *cdev)
 {
        static struct usb_configuration config = {
                .bConfigurationValue    = MULTI_CDC_CONFIG_NUM,
@@ -256,7 +256,7 @@ static int cdc_config_register(struct usb_composite_dev *cdev)
 
 #else
 
-static int cdc_config_register(struct usb_composite_dev *cdev)
+static __ref int cdc_config_register(struct usb_composite_dev *cdev)
 {
        return 0;
 }
index bbb6e98c4384292d3446b62f8671decaf0a51c55..561b30efb8ee84de6fc37c33005cdadc6fbcc5ff 100644 (file)
@@ -645,6 +645,7 @@ static int  mv_u3d_ep_disable(struct usb_ep *_ep)
        struct mv_u3d_ep *ep;
        struct mv_u3d_ep_context *ep_context;
        u32 epxcr, direction;
+       unsigned long flags;
 
        if (!_ep)
                return -EINVAL;
@@ -661,7 +662,9 @@ static int  mv_u3d_ep_disable(struct usb_ep *_ep)
        direction = mv_u3d_ep_dir(ep);
 
        /* nuke all pending requests (does flush) */
+       spin_lock_irqsave(&u3d->lock, flags);
        mv_u3d_nuke(ep, -ESHUTDOWN);
+       spin_unlock_irqrestore(&u3d->lock, flags);
 
        /* Disable the endpoint for Rx or Tx and reset the endpoint type */
        if (direction == MV_U3D_EP_DIR_OUT) {
index cc9207473dbc33f204bbd4009eb9e2138f966da6..0ac6064aa3b86b6cd2376324ac9996f8ece1c0a0 100644 (file)
@@ -2054,7 +2054,7 @@ static struct pxa25x_udc memory = {
 /*
  *     probe - binds to the platform device
  */
-static int __init pxa25x_udc_probe(struct platform_device *pdev)
+static int pxa25x_udc_probe(struct platform_device *pdev)
 {
        struct pxa25x_udc *dev = &memory;
        int retval, irq;
@@ -2203,7 +2203,7 @@ static void pxa25x_udc_shutdown(struct platform_device *_dev)
        pullup_off();
 }
 
-static int __exit pxa25x_udc_remove(struct platform_device *pdev)
+static int pxa25x_udc_remove(struct platform_device *pdev)
 {
        struct pxa25x_udc *dev = platform_get_drvdata(pdev);
 
@@ -2294,7 +2294,8 @@ static int pxa25x_udc_resume(struct platform_device *dev)
 
 static struct platform_driver udc_driver = {
        .shutdown       = pxa25x_udc_shutdown,
-       .remove         = __exit_p(pxa25x_udc_remove),
+       .probe          = pxa25x_udc_probe,
+       .remove         = pxa25x_udc_remove,
        .suspend        = pxa25x_udc_suspend,
        .resume         = pxa25x_udc_resume,
        .driver         = {
@@ -2303,7 +2304,7 @@ static struct platform_driver udc_driver = {
        },
 };
 
-module_platform_driver_probe(udc_driver, pxa25x_udc_probe);
+module_platform_driver(udc_driver);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("Frank Becker, Robert Schwebel, David Brownell");
index d69b36a99dbcd8ae5a1bc57275398be86a2562ca..a8a99e4748d522bded4aef1882a7beaafe45603b 100644 (file)
@@ -543,7 +543,7 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
         * FIFO, requests of >512 cause the endpoint to get stuck with a
         * fragment of the end of the transfer in it.
         */
-       if (can_write > 512)
+       if (can_write > 512 && !periodic)
                can_write = 512;
 
        /*
@@ -2475,8 +2475,6 @@ irq_retry:
        if (gintsts & GINTSTS_ErlySusp) {
                dev_dbg(hsotg->dev, "GINTSTS_ErlySusp\n");
                writel(GINTSTS_ErlySusp, hsotg->regs + GINTSTS);
-
-               s3c_hsotg_disconnect(hsotg);
        }
 
        /*
@@ -2962,9 +2960,6 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,
        if (!hsotg)
                return -ENODEV;
 
-       if (!driver || driver != hsotg->driver || !driver->unbind)
-               return -EINVAL;
-
        /* all endpoints should be shutdown */
        for (ep = 0; ep < hsotg->num_of_eps; ep++)
                s3c_hsotg_ep_disable(&hsotg->eps[ep].ep);
@@ -2972,15 +2967,15 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,
        spin_lock_irqsave(&hsotg->lock, flags);
 
        s3c_hsotg_phy_disable(hsotg);
-       regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
 
-       hsotg->driver = NULL;
+       if (!driver)
+               hsotg->driver = NULL;
+
        hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 
        spin_unlock_irqrestore(&hsotg->lock, flags);
 
-       dev_info(hsotg->dev, "unregistered gadget driver '%s'\n",
-                driver->driver.name);
+       regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
 
        return 0;
 }
index df13d425e9c5fd4700db812505978c4876ac5dd7..205f4a336583de6c32b608854a943cc121dc1dc4 100644 (file)
@@ -227,8 +227,7 @@ static int bcma_hcd_probe(struct bcma_device *dev)
 
        /* TODO: Probably need checks here; is the core connected? */
 
-       if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
-           dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
+       if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32)))
                return -EOPNOTSUPP;
 
        usb_dev = kzalloc(sizeof(struct bcma_hcd_device), GFP_KERNEL);
index 3b645ff46f7b9f8df67d2d793c1758be26173b21..8e7323e07f794435d001ee2df81135fa5bc2325e 100644 (file)
@@ -90,10 +90,9 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev)
         * Since shared usb code relies on it, set it here for now.
         * Once we have dma capability bindings this can go away.
         */
-       if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
-       if (!pdev->dev.coherent_dma_mask)
-               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       retval = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (retval)
+               goto fail_create_hcd;
 
        hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
        if (!hcd) {
index 947b009009f111ba710954ea639962b4d4008463..f2407b2e8a996210aec7f3e7a442119fd6928924 100644 (file)
@@ -130,7 +130,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
        }
 
        /* Enable USB controller, 83xx or 8536 */
-       if (pdata->have_sysif_regs)
+       if (pdata->have_sysif_regs && pdata->controller_ver < FSL_USB_VER_1_6)
                setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);
 
        /* Don't need to set host mode here. It will be done by tdi_reset() */
@@ -232,15 +232,9 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
        case FSL_USB2_PHY_ULPI:
                if (pdata->have_sysif_regs && pdata->controller_ver) {
                        /* controller version 1.6 or above */
+                       clrbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN);
                        setbits32(non_ehci + FSL_SOC_USB_CTRL,
-                                       ULPI_PHY_CLK_SEL);
-                       /*
-                        * Due to controller issue of PHY_CLK_VALID in ULPI
-                        * mode, we set USB_CTRL_USB_EN before checking
-                        * PHY_CLK_VALID, otherwise PHY_CLK_VALID doesn't work.
-                        */
-                       clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
-                                       UTMI_PHY_EN, USB_CTRL_USB_EN);
+                               ULPI_PHY_CLK_SEL | USB_CTRL_USB_EN);
                }
                portsc |= PORT_PTS_ULPI;
                break;
@@ -270,8 +264,9 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
        if (pdata->have_sysif_regs && pdata->controller_ver &&
            (phy_mode == FSL_USB2_PHY_ULPI)) {
                /* check PHY_CLK_VALID to get phy clk valid */
-               if (!spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) &
-                               PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0)) {
+               if (!(spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) &
+                               PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0) ||
+                               in_be32(non_ehci + FSL_SOC_USB_PRICTRL))) {
                        printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n");
                        return -EINVAL;
                }
@@ -669,7 +664,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
         * generic hardware linkage
         */
        .irq = ehci_irq,
-       .flags = HCD_USB2 | HCD_MEMORY | HCD_BH,
+       .flags = HCD_USB2 | HCD_MEMORY,
 
        /*
         * basic lifecycle operations
index b52a66ce92e8592b123239aa24b724dddfd085fa..83ab51af250f158e735373760f8c008ce6fe0ad8 100644 (file)
@@ -43,7 +43,7 @@ static const struct hc_driver ehci_grlib_hc_driver = {
         * generic hardware linkage
         */
        .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2 | HCD_BH,
+       .flags                  = HCD_MEMORY | HCD_USB2,
 
        /*
         * basic lifecycle operations
index 5d6022f30ebe94b2228c6b38851217af1ee8f477..86ab9fd9fe9e938fc29cadeac72a935e8c26b8ff 100644 (file)
@@ -1158,7 +1158,7 @@ static const struct hc_driver ehci_hc_driver = {
         * generic hardware linkage
         */
        .irq =                  ehci_irq,
-       .flags =                HCD_MEMORY | HCD_USB2 | HCD_BH,
+       .flags =                HCD_MEMORY | HCD_USB2,
 
        /*
         * basic lifecycle operations
index 417c10da945078e37ddf20e7be290e996936074e..35cdbd88bbbef62a93a3aa869c12dbfda8183bf2 100644 (file)
@@ -96,7 +96,7 @@ static const struct hc_driver mv_ehci_hc_driver = {
         * generic hardware linkage
         */
        .irq = ehci_irq,
-       .flags = HCD_MEMORY | HCD_USB2 | HCD_BH,
+       .flags = HCD_MEMORY | HCD_USB2,
 
        /*
         * basic lifecycle operations
index ab0397e4d8f3eadae916d07434f4431f3d59def3..323a02b1a0a65778b0e7dd74ad9423e632444402 100644 (file)
@@ -51,7 +51,7 @@ static const struct hc_driver ehci_octeon_hc_driver = {
         * generic hardware linkage
         */
        .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2 | HCD_BH,
+       .flags                  = HCD_MEMORY | HCD_USB2,
 
        /*
         * basic lifecycle operations
@@ -116,8 +116,10 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev)
         * We can DMA from anywhere. But the descriptors must be in
         * the lower 4GB.
         */
-       pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
        pdev->dev.dma_mask = &ehci_octeon_dma_mask;
+       ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        hcd = usb_create_hcd(&ehci_octeon_hc_driver, &pdev->dev, "octeon");
        if (!hcd)
index 78b01fa475bbfc85e0aa35fcd9ab917b963689ee..6fa82d6b7661bea07d38dd249d76a80843ff4d01 100644 (file)
@@ -104,7 +104,7 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
        struct resource *res;
        struct usb_hcd  *hcd;
        void __iomem *regs;
-       int ret = -ENODEV;
+       int ret;
        int irq;
        int i;
        struct omap_hcd *omap;
@@ -144,11 +144,11 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
         * Since shared usb code relies on it, set it here for now.
         * Once we have dma capability bindings this can go away.
         */
-       if (!dev->dma_mask)
-               dev->dma_mask = &dev->coherent_dma_mask;
-       if (!dev->coherent_dma_mask)
-               dev->coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
+       ret = -ENODEV;
        hcd = usb_create_hcd(&ehci_omap_hc_driver, dev,
                        dev_name(dev));
        if (!hcd) {
index d1dfb9db5b420845edec3a30b81bdd30792704e9..2ba76730e6509ea8f9372234be96f9ea81796cd1 100644 (file)
@@ -180,10 +180,9 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)
         * set. Since shared usb code relies on it, set it here for
         * now. Once we have dma capability bindings this can go away.
         */
-       if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
-       if (!pdev->dev.coherent_dma_mask)
-               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       err = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (err)
+               goto err1;
 
        if (!request_mem_region(res->start, resource_size(res),
                                ehci_orion_hc_driver.description)) {
index 6bd299e61f58d23202183f3186c9542f99e93a23..854c2ec7b699d4effe2c9ca6ae4ab264e1a73cd8 100644 (file)
@@ -361,7 +361,7 @@ static struct pci_driver ehci_pci_driver = {
        .remove =       usb_hcd_pci_remove,
        .shutdown =     usb_hcd_pci_shutdown,
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
        .driver =       {
                .pm =   &usb_hcd_pci_pm_ops
        },
index f6b790ca8cf2415805d827fcceebbde48291a935..7f30b7168d5a53542cdbea786d9cba849a932579 100644 (file)
@@ -78,7 +78,7 @@ static int ehci_platform_probe(struct platform_device *dev)
        struct resource *res_mem;
        struct usb_ehci_pdata *pdata;
        int irq;
-       int err = -ENOMEM;
+       int err;
 
        if (usb_disabled())
                return -ENODEV;
@@ -89,10 +89,10 @@ static int ehci_platform_probe(struct platform_device *dev)
         */
        if (!dev_get_platdata(&dev->dev))
                dev->dev.platform_data = &ehci_platform_defaults;
-       if (!dev->dev.dma_mask)
-               dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
-       if (!dev->dev.coherent_dma_mask)
-               dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
+       err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
+       if (err)
+               return err;
 
        pdata = dev_get_platdata(&dev->dev);
 
index 893b707f0000abf0e323f39b28b6060a3293bcef..601e208bd782c07e9d0bb1b60d238ccbb7774758 100644 (file)
@@ -286,7 +286,7 @@ static const struct hc_driver ehci_msp_hc_driver = {
 #else
        .irq =                  ehci_irq,
 #endif
-       .flags =                HCD_MEMORY | HCD_USB2 | HCD_BH,
+       .flags =                HCD_MEMORY | HCD_USB2,
 
        /*
         * basic lifecycle operations
index 6cc5567bf9c87faaa8c4a21dcb4202e8e6e7fb94..932293fa32de657de2e36ba091127e50009a6ff7 100644 (file)
@@ -28,7 +28,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
         * generic hardware linkage
         */
        .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2 | HCD_BH,
+       .flags                  = HCD_MEMORY | HCD_USB2,
 
        /*
         * basic lifecycle operations
index 8188542ba17ea01214a3ab0f269fe07cb6cb1744..fd983771b02559cb56c6210e6813d9b223a80f7a 100644 (file)
@@ -71,7 +71,7 @@ static const struct hc_driver ps3_ehci_hc_driver = {
        .product_desc           = "PS3 EHCI Host Controller",
        .hcd_priv_size          = sizeof(struct ehci_hcd),
        .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2 | HCD_BH,
+       .flags                  = HCD_MEMORY | HCD_USB2,
        .reset                  = ps3_ehci_hc_reset,
        .start                  = ehci_run,
        .stop                   = ehci_stop,
index e321804c34755553afcf3c1ceab38678ed27af1b..a7f776a13eb17133459f23ac584b60287e544197 100644 (file)
@@ -247,6 +247,8 @@ static int qtd_copy_status (
 
 static void
 ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status)
+__releases(ehci->lock)
+__acquires(ehci->lock)
 {
        if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
                /* ... update hc-wide periodic stats */
@@ -272,8 +274,11 @@ ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status)
                urb->actual_length, urb->transfer_buffer_length);
 #endif
 
+       /* complete() can reenter this HCD */
        usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
+       spin_unlock (&ehci->lock);
        usb_hcd_giveback_urb(ehci_to_hcd(ehci), urb, status);
+       spin_lock (&ehci->lock);
 }
 
 static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
index 7c3de95c7054339a5f62b64322f55a24f2bb286b..d919ed47bd47fdc8f631b1804e74bd54e134cf17 100644 (file)
@@ -89,10 +89,9 @@ static int s5p_ehci_probe(struct platform_device *pdev)
         * Since shared usb code relies on it, set it here for now.
         * Once we move to full device tree support this will vanish off.
         */
-       if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
-       if (!pdev->dev.coherent_dma_mask)
-               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       err = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (err)
+               return err;
 
        s5p_setup_vbus_gpio(pdev);
 
index 8a734498079bc176938c57a6b132c146e9be00dd..b2de52d3961488f249aeb9d4026efe2d603b72bb 100644 (file)
@@ -55,7 +55,7 @@ const struct hc_driver ehci_sead3_hc_driver = {
         * generic hardware linkage
         */
        .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2 | HCD_BH,
+       .flags                  = HCD_MEMORY | HCD_USB2,
 
        /*
         * basic lifecycle operations
index dc899eb2b86183561351d78e8dba1ceffc9cbb18..93e59a13bc1fec919ef81690bbce9f4bdcd3e951 100644 (file)
@@ -36,7 +36,7 @@ static const struct hc_driver ehci_sh_hc_driver = {
         * generic hardware linkage
         */
        .irq                            = ehci_irq,
-       .flags                          = HCD_USB2 | HCD_MEMORY | HCD_BH,
+       .flags                          = HCD_USB2 | HCD_MEMORY,
 
        /*
         * basic lifecycle operations
index 1cf0adba3fc8dd4b3e071e8eeef769c5e9fbf1a2..ee6f9ffaa0e73ef9a6ca237d4e28960162e01d51 100644 (file)
@@ -81,10 +81,9 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
         * Since shared usb code relies on it, set it here for now.
         * Once we have dma capability bindings this can go away.
         */
-       if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
-       if (!pdev->dev.coherent_dma_mask)
-               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       retval = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (retval)
+               goto fail;
 
        usbh_clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(usbh_clk)) {
index 78fa76da332435a83cc3c55226d33cbeb2e78afe..e74aaf3f016450a84ee42600ce584bebab41d9b0 100644 (file)
@@ -362,10 +362,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)
         * Since shared usb code relies on it, set it here for now.
         * Once we have dma capability bindings this can go away.
         */
-       if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
-       if (!pdev->dev.coherent_dma_mask)
-               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       err = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (err)
+               return err;
 
        hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev,
                                        dev_name(&pdev->dev));
index 67026ffbf9a871c9780a4b0b7f0d6c739c904e73..cca4be90a864dba009c852f606653fb5fe60d568 100644 (file)
@@ -61,7 +61,7 @@ static const struct hc_driver ehci_tilegx_hc_driver = {
         * Generic hardware linkage.
         */
        .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2 | HCD_BH,
+       .flags                  = HCD_MEMORY | HCD_USB2,
 
        /*
         * Basic lifecycle operations.
index 1c370dfbee0d35e6a3cf2b1288836df2116599c5..59e0e24c753febfb76369be8f872cb3731c2f365 100644 (file)
@@ -108,7 +108,7 @@ static const struct hc_driver ehci_w90x900_hc_driver = {
         * generic hardware linkage
         */
        .irq = ehci_irq,
-       .flags = HCD_USB2|HCD_MEMORY|HCD_BH,
+       .flags = HCD_USB2|HCD_MEMORY,
 
        /*
         * basic lifecycle operations
index 95979f9f4381d8e8e573c7e0fe254d5585d23ab8..eba962e6ebfbbd8ffdd46a85e0fed5ec9b18b78a 100644 (file)
@@ -79,7 +79,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = {
         * generic hardware linkage
         */
        .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2 | HCD_BH,
+       .flags                  = HCD_MEMORY | HCD_USB2,
 
        /*
         * basic lifecycle operations
index 9e0020d9e4c8cc01353ef4b804a9ba9d50bc8cfd..abd5050a4899bdb4518294175477a418583c4e83 100644 (file)
@@ -24,7 +24,7 @@ struct fsl_usb2_dev_data {
        enum fsl_usb2_operating_modes op_mode;  /* operating mode */
 };
 
-struct fsl_usb2_dev_data dr_mode_data[] = {
+static struct fsl_usb2_dev_data dr_mode_data[] = {
        {
                .dr_mode = "host",
                .drivers = { "fsl-ehci", NULL, NULL, },
@@ -42,7 +42,7 @@ struct fsl_usb2_dev_data dr_mode_data[] = {
        },
 };
 
-struct fsl_usb2_dev_data *get_dr_mode_data(struct device_node *np)
+static struct fsl_usb2_dev_data *get_dr_mode_data(struct device_node *np)
 {
        const unsigned char *prop;
        int i;
@@ -75,7 +75,7 @@ static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
        return FSL_USB2_PHY_NONE;
 }
 
-struct platform_device *fsl_usb2_device_register(
+static struct platform_device *fsl_usb2_device_register(
                                        struct platform_device *ofdev,
                                        struct fsl_usb2_platform_data *pdata,
                                        const char *name, int id)
index 60a5de505ca1845609fe34278405e752ddf73226..adb01d950a165f7cf7d5e1a54fe6b674b4cb533a 100644 (file)
@@ -824,13 +824,13 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
                        i = DIV_ROUND_UP(wrap_frame(
                                        cur_frame - urb->start_frame),
                                        urb->interval);
-                       if (urb->transfer_flags & URB_ISO_ASAP) {
+
+                       /* Treat underruns as if URB_ISO_ASAP was set */
+                       if ((urb->transfer_flags & URB_ISO_ASAP) ||
+                                       i >= urb->number_of_packets) {
                                urb->start_frame = wrap_frame(urb->start_frame
                                                + i * urb->interval);
                                i = 0;
-                       } else if (i >= urb->number_of_packets) {
-                               ret = -EXDEV;
-                               goto alloc_dmem_failed;
                        }
                }
        }
index caa3764a34075e4735a9aca7d907f8fa693fde83..36423db63073bc9bce3d6fa28dbf624006f9b6e9 100644 (file)
@@ -524,7 +524,7 @@ MODULE_DEVICE_TABLE(of, at91_ohci_dt_ids);
 static int ohci_at91_of_init(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
-       int i, gpio;
+       int i, gpio, ret;
        enum of_gpio_flags flags;
        struct at91_usbh_data   *pdata;
        u32 ports;
@@ -536,10 +536,9 @@ static int ohci_at91_of_init(struct platform_device *pdev)
         * Since shared usb code relies on it, set it here for now.
         * Once we have dma capability bindings this can go away.
         */
-       if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
-       if (!pdev->dev.coherent_dma_mask)
-               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
index dc6ee9adacf58679305df6baa851167e34e61ed4..866f2464f9de64c84ac96114c96dccb52a472d32 100644 (file)
@@ -114,10 +114,9 @@ static int exynos_ohci_probe(struct platform_device *pdev)
         * Since shared usb code relies on it, set it here for now.
         * Once we move to full device tree support this will vanish off.
         */
-       if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
-       if (!pdev->dev.coherent_dma_mask)
-               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       err = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (err)
+               return err;
 
        exynos_ohci = devm_kzalloc(&pdev->dev, sizeof(struct exynos_ohci_hcd),
                                        GFP_KERNEL);
index 8f6b695af6a470c5f5d5a5ca6a278e3a1186dfcc..604cad1bcf9cd984666aaf0b2b797b48ee6e3382 100644 (file)
@@ -216,31 +216,26 @@ static int ohci_urb_enqueue (
                        frame &= ~(ed->interval - 1);
                        frame |= ed->branch;
                        urb->start_frame = frame;
+                       ed->last_iso = frame + ed->interval * (size - 1);
                }
        } else if (ed->type == PIPE_ISOCHRONOUS) {
                u16     next = ohci_frame_no(ohci) + 1;
                u16     frame = ed->last_iso + ed->interval;
+               u16     length = ed->interval * (size - 1);
 
                /* Behind the scheduling threshold? */
                if (unlikely(tick_before(frame, next))) {
 
-                       /* USB_ISO_ASAP: Round up to the first available slot */
+                       /* URB_ISO_ASAP: Round up to the first available slot */
                        if (urb->transfer_flags & URB_ISO_ASAP) {
                                frame += (next - frame + ed->interval - 1) &
                                                -ed->interval;
 
                        /*
-                        * Not ASAP: Use the next slot in the stream.  If
-                        * the entire URB falls before the threshold, fail.
+                        * Not ASAP: Use the next slot in the stream,
+                        * no matter what.
                         */
                        } else {
-                               if (tick_before(frame + ed->interval *
-                                       (urb->number_of_packets - 1), next)) {
-                                       retval = -EXDEV;
-                                       usb_hcd_unlink_urb_from_ep(hcd, urb);
-                                       goto fail;
-                               }
-
                                /*
                                 * Some OHCI hardware doesn't handle late TDs
                                 * correctly.  After retiring them it proceeds
@@ -251,9 +246,16 @@ static int ohci_urb_enqueue (
                                urb_priv->td_cnt = DIV_ROUND_UP(
                                                (u16) (next - frame),
                                                ed->interval);
+                               if (urb_priv->td_cnt >= urb_priv->length) {
+                                       ++urb_priv->td_cnt;     /* Mark it */
+                                       ohci_dbg(ohci, "iso underrun %p (%u+%u < %u)\n",
+                                                       urb, frame, length,
+                                                       next);
+                               }
                        }
                }
                urb->start_frame = frame;
+               ed->last_iso = frame + length;
        }
 
        /* fill the TDs and link them to the ed; and
index 7d7d507d54e83ef89cdd0695d694f7e3bb4a5e7d..df3eb3e0324ea9ffde44836ed1788cd509d30d19 100644 (file)
@@ -226,8 +226,9 @@ static int usb_hcd_nxp_probe(struct platform_device *pdev)
                return -EPROBE_DEFER;
        }
 
-       pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-       pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+       ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               goto fail_disable;
 
        dev_dbg(&pdev->dev, "%s: " DRIVER_DESC " (nxp)\n", hcd_name);
        if (usb_disabled()) {
index 342dc7e543b81afd5b17377ac351caf2405b7a02..6c16dcef15c6fe0ee47d063a931cd7330c81da29 100644 (file)
@@ -127,8 +127,9 @@ static int ohci_octeon_drv_probe(struct platform_device *pdev)
        }
 
        /* Ohci is a 32-bit device. */
-       pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-       pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+       ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        hcd = usb_create_hcd(&ohci_octeon_hc_driver, &pdev->dev, "octeon");
        if (!hcd)
index a09af26f69ed4efdde274e028eb88110231cfc18..db9bd6bc97b99106a80093d97262401c6862e167 100644 (file)
@@ -132,7 +132,7 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)
        struct usb_hcd          *hcd = NULL;
        void __iomem            *regs = NULL;
        struct resource         *res;
-       int                     ret = -ENODEV;
+       int                     ret;
        int                     irq;
 
        if (usb_disabled())
@@ -166,11 +166,11 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)
         * Since shared usb code relies on it, set it here for now.
         * Once we have dma capability bindings this can go away.
         */
-       if (!dev->dma_mask)
-               dev->dma_mask = &dev->coherent_dma_mask;
-       if (!dev->coherent_dma_mask)
-               dev->coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
+       if (ret)
+               goto err_io;
 
+       ret = -ENODEV;
        hcd = usb_create_hcd(&ohci_omap3_hc_driver, dev,
                        dev_name(dev));
        if (!hcd) {
index 93371a235e821fac080068f7522bc5a80576119c..b64949bc43e2ebacc1620a76faf6d9db2935b16e 100644 (file)
@@ -287,6 +287,7 @@ static int ohci_pxa_of_init(struct platform_device *pdev)
        struct device_node *np = pdev->dev.of_node;
        struct pxaohci_platform_data *pdata;
        u32 tmp;
+       int ret;
 
        if (!np)
                return 0;
@@ -295,10 +296,9 @@ static int ohci_pxa_of_init(struct platform_device *pdev)
         * Since shared usb code relies on it, set it here for now.
         * Once we have dma capability bindings this can go away.
         */
-       if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
-       if (!pdev->dev.coherent_dma_mask)
-               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
index df4a6707322d322dc292e4d11bfdf926e34dd3ce..e7f577e636240b25a74f6b5f4b43c9ebdc99e9de 100644 (file)
@@ -41,9 +41,13 @@ finish_urb(struct ohci_hcd *ohci, struct urb *urb, int status)
 __releases(ohci->lock)
 __acquires(ohci->lock)
 {
-        struct device *dev = ohci_to_hcd(ohci)->self.controller;
+       struct device *dev = ohci_to_hcd(ohci)->self.controller;
+       struct usb_host_endpoint *ep = urb->ep;
+       struct urb_priv *urb_priv;
+
        // ASSERT (urb->hcpriv != 0);
 
+ restart:
        urb_free_priv (ohci, urb->hcpriv);
        urb->hcpriv = NULL;
        if (likely(status == -EINPROGRESS))
@@ -80,6 +84,21 @@ __acquires(ohci->lock)
                ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_IE);
                ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
        }
+
+       /*
+        * An isochronous URB that is sumitted too late won't have any TDs
+        * (marked by the fact that the td_cnt value is larger than the
+        * actual number of TDs).  If the next URB on this endpoint is like
+        * that, give it back now.
+        */
+       if (!list_empty(&ep->urb_list)) {
+               urb = list_first_entry(&ep->urb_list, struct urb, urb_list);
+               urb_priv = urb->hcpriv;
+               if (urb_priv->td_cnt > urb_priv->length) {
+                       status = 0;
+                       goto restart;
+               }
+       }
 }
 
 
@@ -546,7 +565,6 @@ td_fill (struct ohci_hcd *ohci, u32 info,
                td->hwCBP = cpu_to_hc32 (ohci, data & 0xFFFFF000);
                *ohci_hwPSWp(ohci, td, 0) = cpu_to_hc16 (ohci,
                                                (data & 0x0FFF) | 0xE000);
-               td->ed->last_iso = info & 0xffff;
        } else {
                td->hwCBP = cpu_to_hc32 (ohci, data);
        }
@@ -996,7 +1014,7 @@ rescan_this:
                        urb_priv->td_cnt++;
 
                        /* if URB is done, clean up */
-                       if (urb_priv->td_cnt == urb_priv->length) {
+                       if (urb_priv->td_cnt >= urb_priv->length) {
                                modified = completed = 1;
                                finish_urb(ohci, urb, 0);
                        }
@@ -1086,7 +1104,7 @@ static void takeback_td(struct ohci_hcd *ohci, struct td *td)
        urb_priv->td_cnt++;
 
        /* If all this urb's TDs are done, call complete() */
-       if (urb_priv->td_cnt == urb_priv->length)
+       if (urb_priv->td_cnt >= urb_priv->length)
                finish_urb(ohci, urb, status);
 
        /* clean schedule:  unlink EDs that are no longer busy */
index 17b2a7dad77b81cb8d7edb8e69a97ae490d78a63..aa9e127bbe718d52b8c994910c2c30826f5db06e 100644 (file)
@@ -185,6 +185,12 @@ static int ohci_hcd_sa1111_probe(struct sa1111_dev *dev)
        if (usb_disabled())
                return -ENODEV;
 
+       /*
+        * We don't call dma_set_mask_and_coherent() here because the
+        * DMA mask has already been appropraitely setup by the core
+        * SA-1111 bus code (which includes bug workarounds.)
+        */
+
        hcd = usb_create_hcd(&ohci_sa1111_hc_driver, &dev->dev, "sa1111");
        if (!hcd)
                return -ENOMEM;
index cc9dd9e4f05e69469eeca87233dd0f29bac23992..075bb5e9b43fd0c4df8ddf63cfceffcc5ba1c81f 100644 (file)
@@ -111,10 +111,9 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
         * Since shared usb code relies on it, set it here for now.
         * Once we have dma capability bindings this can go away.
         */
-       if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
-       if (!pdev->dev.coherent_dma_mask)
-               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       retval = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (retval)
+               goto fail;
 
        usbh_clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(usbh_clk)) {
index 74af2c6287d2670b321e1edb317f01c0ed2f333b..0196f766df734f48352fd8c5217d08963aab444f 100644 (file)
@@ -163,8 +163,7 @@ static int ssb_hcd_probe(struct ssb_device *dev,
 
        /* TODO: Probably need checks here; is the core connected? */
 
-       if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
-           dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
+       if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32)))
                return -EOPNOTSUPP;
 
        usb_dev = kzalloc(sizeof(struct ssb_hcd_device), GFP_KERNEL);
index c300bd2f7d1c53e0ee684b0c6f9cab185fb1c55c..0f228c46eedaab97c9351f784b8604d6144bb517 100644 (file)
@@ -293,7 +293,7 @@ static struct pci_driver uhci_pci_driver = {
        .remove =       usb_hcd_pci_remove,
        .shutdown =     uhci_shutdown,
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
        .driver =       {
                .pm =   &usb_hcd_pci_pm_ops
        },
index d033a0ec7f0d02bd3874ae5e7339d43e964d2611..f8548b72f7089c1d3e10bebf1f8c070759798b7e 100644 (file)
@@ -75,10 +75,9 @@ static int uhci_hcd_platform_probe(struct platform_device *pdev)
         * Since shared usb code relies on it, set it here for now.
         * Once we have dma capability bindings this can go away.
         */
-       if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
-       if (!pdev->dev.coherent_dma_mask)
-               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        hcd = usb_create_hcd(&uhci_platform_hc_driver, &pdev->dev,
                        pdev->name);
index 041c6ddb695c8ec6fa17d371fe7904de2e47d5ab..da6f56d996ce56f61cd1be20a093c2c16ff54702 100644 (file)
@@ -1303,7 +1303,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
                }
 
                /* Fell behind? */
-               if (uhci_frame_before_eq(frame, next)) {
+               if (!uhci_frame_before_eq(next, frame)) {
 
                        /* USB_ISO_ASAP: Round up to the first available slot */
                        if (urb->transfer_flags & URB_ISO_ASAP)
@@ -1311,13 +1311,17 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
                                                -qh->period;
 
                        /*
-                        * Not ASAP: Use the next slot in the stream.  If
-                        * the entire URB falls before the threshold, fail.
+                        * Not ASAP: Use the next slot in the stream,
+                        * no matter what.
                         */
                        else if (!uhci_frame_before_eq(next,
                                        frame + (urb->number_of_packets - 1) *
                                                qh->period))
-                               return -EXDEV;
+                               dev_dbg(uhci_dev(uhci), "iso underrun %p (%u+%u < %u)\n",
+                                               urb, frame,
+                                               (urb->number_of_packets - 1) *
+                                                       qh->period,
+                                               next);
                }
        }
 
index fae697ed0b708352e06e6e6135a2b49ece4ea34a..773a6b28c4f1657670547265e0d73caed6366907 100644 (file)
@@ -287,7 +287,7 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
                if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue)
                        xhci_queue_stop_endpoint(xhci, slot_id, i, suspend);
        }
-       cmd->command_trb = xhci->cmd_ring->enqueue;
+       cmd->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
        list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list);
        xhci_queue_stop_endpoint(xhci, slot_id, 0, suspend);
        xhci_ring_cmd_db(xhci);
@@ -552,11 +552,15 @@ void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, u16 wIndex)
  *  - Mark a port as being done with device resume,
  *    and ring the endpoint doorbells.
  *  - Stop the Synopsys redriver Compliance Mode polling.
+ *  - Drop and reacquire the xHCI lock, in order to wait for port resume.
  */
 static u32 xhci_get_port_status(struct usb_hcd *hcd,
                struct xhci_bus_state *bus_state,
                __le32 __iomem **port_array,
-               u16 wIndex, u32 raw_port_status)
+               u16 wIndex, u32 raw_port_status,
+               unsigned long flags)
+       __releases(&xhci->lock)
+       __acquires(&xhci->lock)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
        u32 status = 0;
@@ -591,21 +595,42 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
                        return 0xffffffff;
                if (time_after_eq(jiffies,
                                        bus_state->resume_done[wIndex])) {
+                       int time_left;
+
                        xhci_dbg(xhci, "Resume USB2 port %d\n",
                                        wIndex + 1);
                        bus_state->resume_done[wIndex] = 0;
                        clear_bit(wIndex, &bus_state->resuming_ports);
+
+                       set_bit(wIndex, &bus_state->rexit_ports);
                        xhci_set_link_state(xhci, port_array, wIndex,
                                        XDEV_U0);
-                       xhci_dbg(xhci, "set port %d resume\n",
-                                       wIndex + 1);
-                       slot_id = xhci_find_slot_id_by_port(hcd, xhci,
-                                       wIndex + 1);
-                       if (!slot_id) {
-                               xhci_dbg(xhci, "slot_id is zero\n");
-                               return 0xffffffff;
+
+                       spin_unlock_irqrestore(&xhci->lock, flags);
+                       time_left = wait_for_completion_timeout(
+                                       &bus_state->rexit_done[wIndex],
+                                       msecs_to_jiffies(
+                                               XHCI_MAX_REXIT_TIMEOUT));
+                       spin_lock_irqsave(&xhci->lock, flags);
+
+                       if (time_left) {
+                               slot_id = xhci_find_slot_id_by_port(hcd,
+                                               xhci, wIndex + 1);
+                               if (!slot_id) {
+                                       xhci_dbg(xhci, "slot_id is zero\n");
+                                       return 0xffffffff;
+                               }
+                               xhci_ring_device(xhci, slot_id);
+                       } else {
+                               int port_status = xhci_readl(xhci,
+                                               port_array[wIndex]);
+                               xhci_warn(xhci, "Port resume took longer than %i msec, port status = 0x%x\n",
+                                               XHCI_MAX_REXIT_TIMEOUT,
+                                               port_status);
+                               status |= USB_PORT_STAT_SUSPEND;
+                               clear_bit(wIndex, &bus_state->rexit_ports);
                        }
-                       xhci_ring_device(xhci, slot_id);
+
                        bus_state->port_c_suspend |= 1 << wIndex;
                        bus_state->suspended_ports &= ~(1 << wIndex);
                } else {
@@ -728,7 +753,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        break;
                }
                status = xhci_get_port_status(hcd, bus_state, port_array,
-                               wIndex, temp);
+                               wIndex, temp, flags);
                if (status == 0xffffffff)
                        goto error;
 
index 53b972c2a09f10be38a474042d03757618bc76a4..83bcd13622c3466e655a00166bf6e8076ae198bc 100644 (file)
@@ -2428,6 +2428,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
        for (i = 0; i < USB_MAXCHILDREN; ++i) {
                xhci->bus_state[0].resume_done[i] = 0;
                xhci->bus_state[1].resume_done[i] = 0;
+               /* Only the USB 2.0 completions will ever be used. */
+               init_completion(&xhci->bus_state[1].rexit_done[i]);
        }
 
        if (scratchpad_alloc(xhci, flags))
index c2d495057eb538a74db9a01fc69af12442ca8d45..236c3aabe94083ab5c1829241a46a20d39829587 100644 (file)
@@ -351,7 +351,7 @@ static struct pci_driver xhci_pci_driver = {
        /* suspend and resume implemented later */
 
        .shutdown =     usb_hcd_pci_shutdown,
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
        .driver = {
                .pm = &usb_hcd_pci_pm_ops
        },
index 411da1fc7ae8ad0550df9cecb8d5a4bdab0fa543..6bfbd80ec2b9edfa0a079767381d7d733d8c7035 100644 (file)
@@ -123,6 +123,16 @@ static int enqueue_is_link_trb(struct xhci_ring *ring)
        return TRB_TYPE_LINK_LE32(link->control);
 }
 
+union xhci_trb *xhci_find_next_enqueue(struct xhci_ring *ring)
+{
+       /* Enqueue pointer can be left pointing to the link TRB,
+        * we must handle that
+        */
+       if (TRB_TYPE_LINK_LE32(ring->enqueue->link.control))
+               return ring->enq_seg->next->trbs;
+       return ring->enqueue;
+}
+
 /* Updates trb to point to the next TRB in the ring, and updates seg if the next
  * TRB is in a new segment.  This does not skip over link TRBs, and it does not
  * effect the ring dequeue or enqueue pointers.
@@ -859,8 +869,12 @@ remove_finished_td:
                /* Otherwise ring the doorbell(s) to restart queued transfers */
                ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
        }
-       ep->stopped_td = NULL;
-       ep->stopped_trb = NULL;
+
+       /* Clear stopped_td and stopped_trb if endpoint is not halted */
+       if (!(ep->ep_state & EP_HALTED)) {
+               ep->stopped_td = NULL;
+               ep->stopped_trb = NULL;
+       }
 
        /*
         * Drop the lock and complete the URBs in the cancelled TD list.
@@ -1414,6 +1428,12 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
                        inc_deq(xhci, xhci->cmd_ring);
                        return;
                }
+               /* There is no command to handle if we get a stop event when the
+                * command ring is empty, event->cmd_trb points to the next
+                * unset command
+                */
+               if (xhci->cmd_ring->dequeue == xhci->cmd_ring->enqueue)
+                       return;
        }
 
        switch (le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3])
@@ -1743,6 +1763,19 @@ static void handle_port_status(struct xhci_hcd *xhci,
                }
        }
 
+       /*
+        * Check to see if xhci-hub.c is waiting on RExit to U0 transition (or
+        * RExit to a disconnect state).  If so, let the the driver know it's
+        * out of the RExit state.
+        */
+       if (!DEV_SUPERSPEED(temp) &&
+                       test_and_clear_bit(faked_port_index,
+                               &bus_state->rexit_ports)) {
+               complete(&bus_state->rexit_done[faked_port_index]);
+               bogus_port_status = true;
+               goto cleanup;
+       }
+
        if (hcd->speed != HCD_USB3)
                xhci_test_and_clear_bit(xhci, port_array, faked_port_index,
                                        PORT_PLC);
index 49b6edb84a79eccfd5f935db8e03bad0957ee5ad..1e36dbb4836693dbe5ac90b8231361f82645a7b1 100644 (file)
@@ -2598,15 +2598,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
        if (command) {
                cmd_completion = command->completion;
                cmd_status = &command->status;
-               command->command_trb = xhci->cmd_ring->enqueue;
-
-               /* Enqueue pointer can be left pointing to the link TRB,
-                * we must handle that
-                */
-               if (TRB_TYPE_LINK_LE32(command->command_trb->link.control))
-                       command->command_trb =
-                               xhci->cmd_ring->enq_seg->next->trbs;
-
+               command->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
                list_add_tail(&command->cmd_list, &virt_dev->cmd_list);
        } else {
                cmd_completion = &virt_dev->cmd_completion;
@@ -2614,7 +2606,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
        }
        init_completion(cmd_completion);
 
-       cmd_trb = xhci->cmd_ring->dequeue;
+       cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
        if (!ctx_change)
                ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma,
                                udev->slot_id, must_succeed);
@@ -3439,14 +3431,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
 
        /* Attempt to submit the Reset Device command to the command ring */
        spin_lock_irqsave(&xhci->lock, flags);
-       reset_device_cmd->command_trb = xhci->cmd_ring->enqueue;
-
-       /* Enqueue pointer can be left pointing to the link TRB,
-        * we must handle that
-        */
-       if (TRB_TYPE_LINK_LE32(reset_device_cmd->command_trb->link.control))
-               reset_device_cmd->command_trb =
-                       xhci->cmd_ring->enq_seg->next->trbs;
+       reset_device_cmd->command_trb = xhci_find_next_enqueue(xhci->cmd_ring);
 
        list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list);
        ret = xhci_queue_reset_device(xhci, slot_id);
@@ -3650,7 +3635,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
        union xhci_trb *cmd_trb;
 
        spin_lock_irqsave(&xhci->lock, flags);
-       cmd_trb = xhci->cmd_ring->dequeue;
+       cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
        ret = xhci_queue_slot_control(xhci, TRB_ENABLE_SLOT, 0);
        if (ret) {
                spin_unlock_irqrestore(&xhci->lock, flags);
@@ -3785,7 +3770,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
                                slot_ctx->dev_info >> 27);
 
        spin_lock_irqsave(&xhci->lock, flags);
-       cmd_trb = xhci->cmd_ring->dequeue;
+       cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring);
        ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma,
                                        udev->slot_id);
        if (ret) {
index 46aa14894148962e3aff6c8028f8d07cbcb07951..289fbfbae7463f429ef051602e08e7eccb3e06e8 100644 (file)
@@ -1412,8 +1412,18 @@ struct xhci_bus_state {
        unsigned long           resume_done[USB_MAXCHILDREN];
        /* which ports have started to resume */
        unsigned long           resuming_ports;
+       /* Which ports are waiting on RExit to U0 transition. */
+       unsigned long           rexit_ports;
+       struct completion       rexit_done[USB_MAXCHILDREN];
 };
 
+
+/*
+ * It can take up to 20 ms to transition from RExit to U0 on the
+ * Intel Lynx Point LP xHCI host.
+ */
+#define        XHCI_MAX_REXIT_TIMEOUT  (20 * 1000)
+
 static inline unsigned int hcd_index(struct usb_hcd *hcd)
 {
        if (hcd->speed == HCD_USB3)
@@ -1840,6 +1850,7 @@ int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command,
                union xhci_trb *cmd_trb);
 void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
                unsigned int ep_index, unsigned int stream_id);
+union xhci_trb *xhci_find_next_enqueue(struct xhci_ring *ring);
 
 /* xHCI roothub code */
 void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array,
index 5c310c664218dec6d1e71874ee8dc84f0232fa19..790b22b296b11f527b2060a76e6aa89624d8d804 100644 (file)
@@ -89,7 +89,6 @@ struct am35x_glue {
        struct clk              *phy_clk;
        struct clk              *clk;
 };
-#define glue_to_musb(g)                platform_get_drvdata(g->musb)
 
 /*
  * am35x_musb_enable - enable interrupts
@@ -452,14 +451,18 @@ static const struct musb_platform_ops am35x_ops = {
        .set_vbus       = am35x_musb_set_vbus,
 };
 
-static u64 am35x_dmamask = DMA_BIT_MASK(32);
+static const struct platform_device_info am35x_dev_info = {
+       .name           = "musb-hdrc",
+       .id             = PLATFORM_DEVID_AUTO,
+       .dma_mask       = DMA_BIT_MASK(32),
+};
 
 static int am35x_probe(struct platform_device *pdev)
 {
        struct musb_hdrc_platform_data  *pdata = dev_get_platdata(&pdev->dev);
        struct platform_device          *musb;
        struct am35x_glue               *glue;
-
+       struct platform_device_info     pinfo;
        struct clk                      *phy_clk;
        struct clk                      *clk;
 
@@ -471,12 +474,6 @@ static int am35x_probe(struct platform_device *pdev)
                goto err0;
        }
 
-       musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
-       if (!musb) {
-               dev_err(&pdev->dev, "failed to allocate musb device\n");
-               goto err1;
-       }
-
        phy_clk = clk_get(&pdev->dev, "fck");
        if (IS_ERR(phy_clk)) {
                dev_err(&pdev->dev, "failed to get PHY clock\n");
@@ -503,12 +500,7 @@ static int am35x_probe(struct platform_device *pdev)
                goto err6;
        }
 
-       musb->dev.parent                = &pdev->dev;
-       musb->dev.dma_mask              = &am35x_dmamask;
-       musb->dev.coherent_dma_mask     = am35x_dmamask;
-
        glue->dev                       = &pdev->dev;
-       glue->musb                      = musb;
        glue->phy_clk                   = phy_clk;
        glue->clk                       = clk;
 
@@ -516,22 +508,17 @@ static int am35x_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, glue);
 
-       ret = platform_device_add_resources(musb, pdev->resource,
-                       pdev->num_resources);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to add resources\n");
-               goto err7;
-       }
-
-       ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
-       if (ret) {
-               dev_err(&pdev->dev, "failed to add platform_data\n");
-               goto err7;
-       }
-
-       ret = platform_device_add(musb);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to register musb device\n");
+       pinfo = am35x_dev_info;
+       pinfo.parent = &pdev->dev;
+       pinfo.res = pdev->resource;
+       pinfo.num_res = pdev->num_resources;
+       pinfo.data = pdata;
+       pinfo.size_data = sizeof(*pdata);
+
+       glue->musb = musb = platform_device_register_full(&pinfo);
+       if (IS_ERR(musb)) {
+               ret = PTR_ERR(musb);
+               dev_err(&pdev->dev, "failed to register musb device: %d\n", ret);
                goto err7;
        }
 
@@ -550,9 +537,6 @@ err4:
        clk_put(phy_clk);
 
 err3:
-       platform_device_put(musb);
-
-err1:
        kfree(glue);
 
 err0:
index d9ddf4122f37e6ddfd19661eb9cb1448306525b6..2f2c1cb364218833f40468429d1469299a56e406 100644 (file)
@@ -472,7 +472,11 @@ static const struct musb_platform_ops da8xx_ops = {
        .set_vbus       = da8xx_musb_set_vbus,
 };
 
-static u64 da8xx_dmamask = DMA_BIT_MASK(32);
+static const struct platform_device_info da8xx_dev_info = {
+       .name           = "musb-hdrc",
+       .id             = PLATFORM_DEVID_AUTO,
+       .dma_mask       = DMA_BIT_MASK(32),
+};
 
 static int da8xx_probe(struct platform_device *pdev)
 {
@@ -480,7 +484,7 @@ static int da8xx_probe(struct platform_device *pdev)
        struct musb_hdrc_platform_data  *pdata = dev_get_platdata(&pdev->dev);
        struct platform_device          *musb;
        struct da8xx_glue               *glue;
-
+       struct platform_device_info     pinfo;
        struct clk                      *clk;
 
        int                             ret = -ENOMEM;
@@ -491,12 +495,6 @@ static int da8xx_probe(struct platform_device *pdev)
                goto err0;
        }
 
-       musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
-       if (!musb) {
-               dev_err(&pdev->dev, "failed to allocate musb device\n");
-               goto err1;
-       }
-
        clk = clk_get(&pdev->dev, "usb20");
        if (IS_ERR(clk)) {
                dev_err(&pdev->dev, "failed to get clock\n");
@@ -510,12 +508,7 @@ static int da8xx_probe(struct platform_device *pdev)
                goto err4;
        }
 
-       musb->dev.parent                = &pdev->dev;
-       musb->dev.dma_mask              = &da8xx_dmamask;
-       musb->dev.coherent_dma_mask     = da8xx_dmamask;
-
        glue->dev                       = &pdev->dev;
-       glue->musb                      = musb;
        glue->clk                       = clk;
 
        pdata->platform_ops             = &da8xx_ops;
@@ -535,22 +528,17 @@ static int da8xx_probe(struct platform_device *pdev)
        musb_resources[1].end = pdev->resource[1].end;
        musb_resources[1].flags = pdev->resource[1].flags;
 
-       ret = platform_device_add_resources(musb, musb_resources,
-                       ARRAY_SIZE(musb_resources));
-       if (ret) {
-               dev_err(&pdev->dev, "failed to add resources\n");
-               goto err5;
-       }
-
-       ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
-       if (ret) {
-               dev_err(&pdev->dev, "failed to add platform_data\n");
-               goto err5;
-       }
-
-       ret = platform_device_add(musb);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to register musb device\n");
+       pinfo = da8xx_dev_info;
+       pinfo.parent = &pdev->dev;
+       pinfo.res = musb_resources;
+       pinfo.num_res = ARRAY_SIZE(musb_resources);
+       pinfo.data = pdata;
+       pinfo.size_data = sizeof(*pdata);
+
+       glue->musb = musb = platform_device_register_full(&pinfo);
+       if (IS_ERR(musb)) {
+               ret = PTR_ERR(musb);
+               dev_err(&pdev->dev, "failed to register musb device: %d\n", ret);
                goto err5;
        }
 
@@ -563,9 +551,6 @@ err4:
        clk_put(clk);
 
 err3:
-       platform_device_put(musb);
-
-err1:
        kfree(glue);
 
 err0:
index ed0834e2b72eeaa6c9dbe73bdb77c2f433282b42..45aae0bbb8dfb2b03f9af13aecd767907ec01ebb 100644 (file)
@@ -505,7 +505,11 @@ static const struct musb_platform_ops davinci_ops = {
        .set_vbus       = davinci_musb_set_vbus,
 };
 
-static u64 davinci_dmamask = DMA_BIT_MASK(32);
+static const struct platform_device_info davinci_dev_info = {
+       .name           = "musb-hdrc",
+       .id             = PLATFORM_DEVID_AUTO,
+       .dma_mask       = DMA_BIT_MASK(32),
+};
 
 static int davinci_probe(struct platform_device *pdev)
 {
@@ -513,6 +517,7 @@ static int davinci_probe(struct platform_device *pdev)
        struct musb_hdrc_platform_data  *pdata = dev_get_platdata(&pdev->dev);
        struct platform_device          *musb;
        struct davinci_glue             *glue;
+       struct platform_device_info     pinfo;
        struct clk                      *clk;
 
        int                             ret = -ENOMEM;
@@ -523,12 +528,6 @@ static int davinci_probe(struct platform_device *pdev)
                goto err0;
        }
 
-       musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
-       if (!musb) {
-               dev_err(&pdev->dev, "failed to allocate musb device\n");
-               goto err1;
-       }
-
        clk = clk_get(&pdev->dev, "usb");
        if (IS_ERR(clk)) {
                dev_err(&pdev->dev, "failed to get clock\n");
@@ -542,12 +541,7 @@ static int davinci_probe(struct platform_device *pdev)
                goto err4;
        }
 
-       musb->dev.parent                = &pdev->dev;
-       musb->dev.dma_mask              = &davinci_dmamask;
-       musb->dev.coherent_dma_mask     = davinci_dmamask;
-
        glue->dev                       = &pdev->dev;
-       glue->musb                      = musb;
        glue->clk                       = clk;
 
        pdata->platform_ops             = &davinci_ops;
@@ -567,22 +561,17 @@ static int davinci_probe(struct platform_device *pdev)
        musb_resources[1].end = pdev->resource[1].end;
        musb_resources[1].flags = pdev->resource[1].flags;
 
-       ret = platform_device_add_resources(musb, musb_resources,
-                       ARRAY_SIZE(musb_resources));
-       if (ret) {
-               dev_err(&pdev->dev, "failed to add resources\n");
-               goto err5;
-       }
-
-       ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
-       if (ret) {
-               dev_err(&pdev->dev, "failed to add platform_data\n");
-               goto err5;
-       }
-
-       ret = platform_device_add(musb);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to register musb device\n");
+       pinfo = davinci_dev_info;
+       pinfo.parent = &pdev->dev;
+       pinfo.res = musb_resources;
+       pinfo.num_res = ARRAY_SIZE(musb_resources);
+       pinfo.data = pdata;
+       pinfo.size_data = sizeof(*pdata);
+
+       glue->musb = musb = platform_device_register_full(&pinfo);
+       if (IS_ERR(musb)) {
+               ret = PTR_ERR(musb);
+               dev_err(&pdev->dev, "failed to register musb device: %d\n", ret);
                goto err5;
        }
 
@@ -595,9 +584,6 @@ err4:
        clk_put(clk);
 
 err3:
-       platform_device_put(musb);
-
-err1:
        kfree(glue);
 
 err0:
index 4047cbb91bac4e541b914801fe8e12c92d923625..bd4138d80a48f243c9d4cb32527196d0024eb3d1 100644 (file)
@@ -535,6 +535,9 @@ static int dsps_probe(struct platform_device *pdev)
        struct dsps_glue *glue;
        int ret;
 
+       if (!strcmp(pdev->name, "musb-hdrc"))
+               return -ENODEV;
+
        match = of_match_node(musb_dsps_of_match, pdev->dev.of_node);
        if (!match) {
                dev_err(&pdev->dev, "fail to get matching of_match struct\n");
index 9a08679d204dfe9ee6fb1ad421813ea329c25abd..b19ed213ab8580c5456cbddaca4f217db31733c4 100644 (file)
@@ -1790,6 +1790,10 @@ int musb_gadget_setup(struct musb *musb)
        musb->g.max_speed = USB_SPEED_HIGH;
        musb->g.speed = USB_SPEED_UNKNOWN;
 
+       MUSB_DEV_MODE(musb);
+       musb->xceiv->otg->default_a = 0;
+       musb->xceiv->state = OTG_STATE_B_IDLE;
+
        /* this "gadget" abstracts/virtualizes the controller */
        musb->g.name = musb_driver_name;
        musb->g.is_otg = 1;
@@ -1849,7 +1853,6 @@ static int musb_gadget_start(struct usb_gadget *g,
        musb->gadget_driver = driver;
 
        spin_lock_irqsave(&musb->lock, flags);
-       musb->is_active = 1;
 
        otg_set_peripheral(otg, &musb->g);
        musb->xceiv->state = OTG_STATE_B_IDLE;
index b3b3ed723882ffab75829e7c9bc1b08b42e1605d..4432314d70ee18f1dfe0e092c487dcab224c1742 100644 (file)
@@ -1152,7 +1152,11 @@ static const struct musb_platform_ops tusb_ops = {
        .set_vbus       = tusb_musb_set_vbus,
 };
 
-static u64 tusb_dmamask = DMA_BIT_MASK(32);
+static const struct platform_device_info tusb_dev_info = {
+       .name           = "musb-hdrc",
+       .id             = PLATFORM_DEVID_AUTO,
+       .dma_mask       = DMA_BIT_MASK(32),
+};
 
 static int tusb_probe(struct platform_device *pdev)
 {
@@ -1160,7 +1164,7 @@ static int tusb_probe(struct platform_device *pdev)
        struct musb_hdrc_platform_data  *pdata = dev_get_platdata(&pdev->dev);
        struct platform_device          *musb;
        struct tusb6010_glue            *glue;
-
+       struct platform_device_info     pinfo;
        int                             ret = -ENOMEM;
 
        glue = kzalloc(sizeof(*glue), GFP_KERNEL);
@@ -1169,18 +1173,7 @@ static int tusb_probe(struct platform_device *pdev)
                goto err0;
        }
 
-       musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
-       if (!musb) {
-               dev_err(&pdev->dev, "failed to allocate musb device\n");
-               goto err1;
-       }
-
-       musb->dev.parent                = &pdev->dev;
-       musb->dev.dma_mask              = &tusb_dmamask;
-       musb->dev.coherent_dma_mask     = tusb_dmamask;
-
        glue->dev                       = &pdev->dev;
-       glue->musb                      = musb;
 
        pdata->platform_ops             = &tusb_ops;
 
@@ -1204,31 +1197,23 @@ static int tusb_probe(struct platform_device *pdev)
        musb_resources[2].end = pdev->resource[2].end;
        musb_resources[2].flags = pdev->resource[2].flags;
 
-       ret = platform_device_add_resources(musb, musb_resources,
-                       ARRAY_SIZE(musb_resources));
-       if (ret) {
-               dev_err(&pdev->dev, "failed to add resources\n");
-               goto err3;
-       }
-
-       ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
-       if (ret) {
-               dev_err(&pdev->dev, "failed to add platform_data\n");
-               goto err3;
-       }
-
-       ret = platform_device_add(musb);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to register musb device\n");
+       pinfo = tusb_dev_info;
+       pinfo.parent = &pdev->dev;
+       pinfo.res = musb_resources;
+       pinfo.num_res = ARRAY_SIZE(musb_resources);
+       pinfo.data = pdata;
+       pinfo.size_data = sizeof(*pdata);
+
+       glue->musb = musb = platform_device_register_full(&pinfo);
+       if (IS_ERR(musb)) {
+               ret = PTR_ERR(musb);
+               dev_err(&pdev->dev, "failed to register musb device: %d\n", ret);
                goto err3;
        }
 
        return 0;
 
 err3:
-       platform_device_put(musb);
-
-err1:
        kfree(glue);
 
 err0:
index b2f29c9aebbfdb15e9e9be8004f2e8d7bf5ed60d..02799a5efcd448b8c38ee85de7cad8452ffbb617 100644 (file)
@@ -241,7 +241,7 @@ static int gpio_vbus_set_suspend(struct usb_phy *phy, int suspend)
 
 /* platform driver interface */
 
-static int __init gpio_vbus_probe(struct platform_device *pdev)
+static int gpio_vbus_probe(struct platform_device *pdev)
 {
        struct gpio_vbus_mach_info *pdata = dev_get_platdata(&pdev->dev);
        struct gpio_vbus_data *gpio_vbus;
@@ -349,7 +349,7 @@ err_gpio:
        return err;
 }
 
-static int __exit gpio_vbus_remove(struct platform_device *pdev)
+static int gpio_vbus_remove(struct platform_device *pdev)
 {
        struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
        struct gpio_vbus_mach_info *pdata = dev_get_platdata(&pdev->dev);
@@ -398,8 +398,6 @@ static const struct dev_pm_ops gpio_vbus_dev_pm_ops = {
 };
 #endif
 
-/* NOTE:  the gpio-vbus device may *NOT* be hotplugged */
-
 MODULE_ALIAS("platform:gpio-vbus");
 
 static struct platform_driver gpio_vbus_driver = {
@@ -410,10 +408,11 @@ static struct platform_driver gpio_vbus_driver = {
                .pm = &gpio_vbus_dev_pm_ops,
 #endif
        },
-       .remove  = __exit_p(gpio_vbus_remove),
+       .probe          = gpio_vbus_probe,
+       .remove         = gpio_vbus_remove,
 };
 
-module_platform_driver_probe(gpio_vbus_driver, gpio_vbus_probe);
+module_platform_driver(gpio_vbus_driver);
 
 MODULE_DESCRIPTION("simple GPIO controlled OTG transceiver driver");
 MODULE_AUTHOR("Philipp Zabel");
index fc15694d3031bbf83b76e932914e44251280d491..4e8a0405f956c478491a1ed6f18d65a9afc07e9a 100644 (file)
@@ -79,7 +79,7 @@ static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate)
                        return &dpll_map[i].params;
        }
 
-       return 0;
+       return NULL;
 }
 
 static int omap_usb3_suspend(struct usb_phy *x, int suspend)
index c454bfa22a106184bbaee567e4f49fbad5d8d057..ddb9c51f2c999c04a27aab9d7a2924c429205672 100644 (file)
@@ -60,7 +60,7 @@ config USB_SERIAL_SIMPLE
                - Suunto ANT+ USB device.
                - Fundamental Software dongle.
                - HP4x calculators
-               - a number of Motoroloa phones
+               - a number of Motorola phones
                - Siemens USB/MPI adapter.
                - ViVOtech ViVOpay USB device.
                - Infineon Modem Flashloader USB interface
index 1cf6f125f5f078624b41bd1256686d35f28ee4b7..80a7104d5ddb3e6d81fa125bb13d9a4d0af05dcf 100644 (file)
@@ -81,6 +81,7 @@ static void option_instat_callback(struct urb *urb);
 
 #define HUAWEI_VENDOR_ID                       0x12D1
 #define HUAWEI_PRODUCT_E173                    0x140C
+#define HUAWEI_PRODUCT_E1750                   0x1406
 #define HUAWEI_PRODUCT_K4505                   0x1464
 #define HUAWEI_PRODUCT_K3765                   0x1465
 #define HUAWEI_PRODUCT_K4605                   0x14C6
@@ -567,6 +568,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t) &net_intf1_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1750, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t) &net_intf2_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1441, USB_CLASS_COMM, 0x02, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1442, USB_CLASS_COMM, 0x02, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff),
index e7a84f0f517969fec4bbb59ac270eeb97fbf22d3..bedf8e47713be02dfc80b8a2e3512cb24a455a15 100644 (file)
@@ -139,6 +139,7 @@ enum pl2303_type {
        HX_TA,          /* HX(A) / X(A) / TA version  */ /* TODO: improve */
        HXD_EA_RA_SA,   /* HXD / EA / RA / SA version */ /* TODO: improve */
        TB,             /* TB version */
+       HX_CLONE,       /* Cheap and less functional clone of the HX chip */
 };
 /*
  * NOTE: don't know the difference between type 0 and type 1,
@@ -206,8 +207,23 @@ static int pl2303_startup(struct usb_serial *serial)
                 * the device descriptors of the X/HX, HXD, EA, RA, SA, TA, TB
                 */
                if (le16_to_cpu(serial->dev->descriptor.bcdDevice) == 0x300) {
-                       type = HX_TA;
-                       type_str = "X/HX/TA";
+                       /* Check if the device is a clone */
+                       pl2303_vendor_read(0x9494, 0, serial, buf);
+                       /*
+                        * NOTE: Not sure if this read is really needed.
+                        * The HX returns 0x00, the clone 0x02, but the Windows
+                        * driver seems to ignore the value and continues.
+                        */
+                       pl2303_vendor_write(0x0606, 0xaa, serial);
+                       pl2303_vendor_read(0x8686, 0, serial, buf);
+                       if (buf[0] != 0xaa) {
+                               type = HX_CLONE;
+                               type_str = "X/HX clone (limited functionality)";
+                       } else {
+                               type = HX_TA;
+                               type_str = "X/HX/TA";
+                       }
+                       pl2303_vendor_write(0x0606, 0x00, serial);
                } else if (le16_to_cpu(serial->dev->descriptor.bcdDevice)
                                                                     == 0x400) {
                        type = HXD_EA_RA_SA;
@@ -305,8 +321,9 @@ static int pl2303_baudrate_encode_direct(int baud, enum pl2303_type type,
 {
        /*
         * NOTE: Only the values defined in baud_sup are supported !
-        *       => if unsupported values are set, the PL2303 seems to
-        *          use 9600 baud (at least my PL2303X always does)
+        * => if unsupported values are set, the PL2303 uses 9600 baud instead
+        * => HX clones just don't work at unsupported baud rates < 115200 baud,
+        *    for baud rates > 115200 they run at 115200 baud
         */
        const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600,
                                 4800, 7200, 9600, 14400, 19200, 28800, 38400,
@@ -316,14 +333,14 @@ static int pl2303_baudrate_encode_direct(int baud, enum pl2303_type type,
         * NOTE: With the exception of type_0/1 devices, the following
         * additional baud rates are supported (tested with HX rev. 3A only):
         * 110*, 56000*, 128000, 134400, 161280, 201600, 256000*, 268800,
-        * 403200, 806400.      (*: not HX)
+        * 403200, 806400.      (*: not HX and HX clones)
         *
         * Maximum values: HXD, TB: 12000000; HX, TA: 6000000;
-        *                 type_0+1: 1228800; RA: 921600; SA: 115200
+        *                 type_0+1: 1228800; RA: 921600; HX clones, SA: 115200
         *
         * As long as we are not using this encoding method for anything else
-        * than the type_0+1 and HX chips, there is no point in complicating
-        * the code to support them.
+        * than the type_0+1, HX and HX clone chips, there is no point in
+        * complicating the code to support them.
         */
        int i;
 
@@ -347,6 +364,8 @@ static int pl2303_baudrate_encode_direct(int baud, enum pl2303_type type,
                baud = min_t(int, baud, 6000000);
        else if (type == type_0 || type == type_1)
                baud = min_t(int, baud, 1228800);
+       else if (type == HX_CLONE)
+               baud = min_t(int, baud, 115200);
        /* Direct (standard) baud rate encoding method */
        put_unaligned_le32(baud, buf);
 
@@ -359,7 +378,8 @@ static int pl2303_baudrate_encode_divisor(int baud, enum pl2303_type type,
        /*
         * Divisor based baud rate encoding method
         *
-        * NOTE: it's not clear if the type_0/1 chips support this method
+        * NOTE: HX clones do NOT support this method.
+        * It's not clear if the type_0/1 chips support it.
         *
         * divisor = 12MHz * 32 / baudrate = 2^A * B
         *
@@ -452,7 +472,7 @@ static void pl2303_encode_baudrate(struct tty_struct *tty,
         * 1) Direct method: encodes the baud rate value directly
         *    => supported by all chip types
         * 2) Divisor based method: encodes a divisor to a base value (12MHz*32)
-        *    => supported by HX chips (and likely not by type_0/1 chips)
+        *    => not supported by HX clones (and likely type_0/1 chips)
         *
         * NOTE: Although the divisor based baud rate encoding method is much
         * more flexible, some of the standard baud rate values can not be
@@ -460,7 +480,7 @@ static void pl2303_encode_baudrate(struct tty_struct *tty,
         * the device likely uses the same baud rate generator for both methods
         * so that there is likley no difference.
         */
-       if (type == type_0 || type == type_1)
+       if (type == type_0 || type == type_1 || type == HX_CLONE)
                baud = pl2303_baudrate_encode_direct(baud, type, buf);
        else
                baud = pl2303_baudrate_encode_divisor(baud, type, buf);
@@ -813,6 +833,7 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
        result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                                 BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
                                 0, NULL, 0, 100);
+       /* NOTE: HX clones don't support sending breaks, -EPIPE is returned */
        if (result)
                dev_err(&port->dev, "error sending break = %d\n", result);
 }
index 4b79a1f2f901e86eb7726fd64d1af3bac66e7385..ce5221fa393a8db2ca9f4de61817ae230f3f0bc8 100644 (file)
@@ -461,7 +461,7 @@ static void tcm_vhost_release_cmd(struct se_cmd *se_cmd)
                u32 i;
                for (i = 0; i < tv_cmd->tvc_sgl_count; i++)
                        put_page(sg_page(&tv_cmd->tvc_sgl[i]));
-        }
+       }
 
        tcm_vhost_put_inflight(tv_cmd->inflight);
        percpu_ida_free(&se_sess->sess_tag_pool, se_cmd->map_tag);
@@ -728,7 +728,12 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq,
        }
        se_sess = tv_nexus->tvn_se_sess;
 
-       tag = percpu_ida_alloc(&se_sess->sess_tag_pool, GFP_KERNEL);
+       tag = percpu_ida_alloc(&se_sess->sess_tag_pool, GFP_ATOMIC);
+       if (tag < 0) {
+               pr_err("Unable to obtain tag for tcm_vhost_cmd\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
        cmd = &((struct tcm_vhost_cmd *)se_sess->sess_cmd_map)[tag];
        sg = cmd->tvc_sgl;
        pages = cmd->tvc_upages;
@@ -1373,21 +1378,30 @@ static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
        return 0;
 }
 
+static void vhost_scsi_free(struct vhost_scsi *vs)
+{
+       if (is_vmalloc_addr(vs))
+               vfree(vs);
+       else
+               kfree(vs);
+}
+
 static int vhost_scsi_open(struct inode *inode, struct file *f)
 {
        struct vhost_scsi *vs;
        struct vhost_virtqueue **vqs;
-       int r, i;
+       int r = -ENOMEM, i;
 
-       vs = kzalloc(sizeof(*vs), GFP_KERNEL);
-       if (!vs)
-               return -ENOMEM;
+       vs = kzalloc(sizeof(*vs), GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
+       if (!vs) {
+               vs = vzalloc(sizeof(*vs));
+               if (!vs)
+                       goto err_vs;
+       }
 
        vqs = kmalloc(VHOST_SCSI_MAX_VQ * sizeof(*vqs), GFP_KERNEL);
-       if (!vqs) {
-               kfree(vs);
-               return -ENOMEM;
-       }
+       if (!vqs)
+               goto err_vqs;
 
        vhost_work_init(&vs->vs_completion_work, vhost_scsi_complete_cmd_work);
        vhost_work_init(&vs->vs_event_work, tcm_vhost_evt_work);
@@ -1407,14 +1421,18 @@ static int vhost_scsi_open(struct inode *inode, struct file *f)
 
        tcm_vhost_init_inflight(vs, NULL);
 
-       if (r < 0) {
-               kfree(vqs);
-               kfree(vs);
-               return r;
-       }
+       if (r < 0)
+               goto err_init;
 
        f->private_data = vs;
        return 0;
+
+err_init:
+       kfree(vqs);
+err_vqs:
+       vhost_scsi_free(vs);
+err_vs:
+       return r;
 }
 
 static int vhost_scsi_release(struct inode *inode, struct file *f)
@@ -1431,7 +1449,7 @@ static int vhost_scsi_release(struct inode *inode, struct file *f)
        /* Jobs can re-queue themselves in evt kick handler. Do extra flush. */
        vhost_scsi_flush(vs);
        kfree(vs->dev.vqs);
-       kfree(vs);
+       vhost_scsi_free(vs);
        return 0;
 }
 
index 9a9502a4aa5089519d338ca62b07a557069fb00d..69068e0d8f31af183c075afe3026d60b09a0b55e 100644 (file)
@@ -161,9 +161,11 @@ void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work)
        if (list_empty(&work->node)) {
                list_add_tail(&work->node, &dev->work_list);
                work->queue_seq++;
+               spin_unlock_irqrestore(&dev->work_lock, flags);
                wake_up_process(dev->worker);
+       } else {
+               spin_unlock_irqrestore(&dev->work_lock, flags);
        }
-       spin_unlock_irqrestore(&dev->work_lock, flags);
 }
 EXPORT_SYMBOL_GPL(vhost_work_queue);
 
index 0a2cce7285be99dd8aaa7983a43bbeae7e6b2550..afe4702a5528a0ea9675cdabfce8ee4243e3799a 100644 (file)
@@ -10,6 +10,7 @@
  *
  *  ARM PrimeCell PL110 Color LCD Controller
  */
+#include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -551,6 +552,10 @@ static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
        if (!board)
                return -EINVAL;
 
+       ret = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               goto out;
+
        ret = amba_request_regions(dev, NULL);
        if (ret) {
                printk(KERN_ERR "CLCD: unable to reserve regs region\n");
index 75dca19bf2149a968f733ed1ff8a0cd468baa745..6ac755270ab46d1a3ef830c89338c0daab519664 100644 (file)
@@ -514,7 +514,7 @@ static int mmphw_probe(struct platform_device *pdev)
        if (IS_ERR(ctrl->clk)) {
                dev_err(ctrl->dev, "unable to get clk %s\n", mi->clk_name);
                ret = -ENOENT;
-               goto failed_get_clk;
+               goto failed;
        }
        clk_prepare_enable(ctrl->clk);
 
@@ -551,21 +551,8 @@ failed_path_init:
                path_deinit(path_plat);
        }
 
-       if (ctrl->clk) {
-               devm_clk_put(ctrl->dev, ctrl->clk);
-               clk_disable_unprepare(ctrl->clk);
-       }
-failed_get_clk:
-       devm_free_irq(ctrl->dev, ctrl->irq, ctrl);
+       clk_disable_unprepare(ctrl->clk);
 failed:
-       if (ctrl) {
-               if (ctrl->reg_base)
-                       devm_iounmap(ctrl->dev, ctrl->reg_base);
-               devm_release_mem_region(ctrl->dev, res->start,
-                               resource_size(res));
-               devm_kfree(ctrl->dev, ctrl);
-       }
-
        dev_err(&pdev->dev, "device init failed\n");
 
        return ret;
index d250ed0f806d3bf66d858e9f633852f3baa58f4d..27197a8048c0a7aa9ffcbd3c8a2280ae12866dcc 100644 (file)
@@ -620,6 +620,7 @@ static int mxsfb_restore_mode(struct mxsfb_info *host)
                break;
        case 3:
                bits_per_pixel = 32;
+               break;
        case 1:
        default:
                return -EINVAL;
index 7ef079c146e7242c9edee33cc43bc0cd3c850ce1..c172a5281f9e6c9369b0cec236e3bbf2abb875ac 100644 (file)
@@ -2075,6 +2075,7 @@ static int neofb_probe(struct pci_dev *dev, const struct pci_device_id *id)
        if (!fb_find_mode(&info->var, info, mode_option, NULL, 0,
                        info->monspecs.modedb, 16)) {
                printk(KERN_ERR "neofb: Unable to find usable video mode.\n");
+               err = -EINVAL;
                goto err_map_video;
        }
 
@@ -2097,7 +2098,8 @@ static int neofb_probe(struct pci_dev *dev, const struct pci_device_id *id)
               info->fix.smem_len >> 10, info->var.xres,
               info->var.yres, h_sync / 1000, h_sync % 1000, v_sync);
 
-       if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
+       err = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (err < 0)
                goto err_map_video;
 
        err = register_framebuffer(info);
index 171821ddd78de381a866e9912bece023a8fcaca5..ba5b40f581f6fdfe1849a3d4d62c8f38ea65dab1 100644 (file)
@@ -120,7 +120,7 @@ int of_get_display_timing(struct device_node *np, const char *name,
                return -EINVAL;
        }
 
-       timing_np = of_find_node_by_name(np, name);
+       timing_np = of_get_child_by_name(np, name);
        if (!timing_np) {
                pr_err("%s: could not find node '%s'\n",
                        of_node_full_name(np), name);
@@ -143,11 +143,11 @@ struct display_timings *of_get_display_timings(struct device_node *np)
        struct display_timings *disp;
 
        if (!np) {
-               pr_err("%s: no devicenode given\n", of_node_full_name(np));
+               pr_err("%s: no device node given\n", of_node_full_name(np));
                return NULL;
        }
 
-       timings_np = of_find_node_by_name(np, "display-timings");
+       timings_np = of_get_child_by_name(np, "display-timings");
        if (!timings_np) {
                pr_err("%s: could not find display-timings node\n",
                        of_node_full_name(np));
index 6c90885b094020f33b74d591db6a93edcbd4aeb7..10b25e7cd878c6e7a5657fd8c1a4865b0935c004 100644 (file)
@@ -35,6 +35,7 @@ config DISPLAY_PANEL_DPI
 
 config DISPLAY_PANEL_DSI_CM
        tristate "Generic DSI Command Mode Panel"
+       depends on BACKLIGHT_CLASS_DEVICE
        help
          Driver for generic DSI command mode panels.
 
index 1b60698f141ed983e2661743f2a5c79f471a02a6..ccd9073f706f6d59242a5b1866d74dcd2c9bffa6 100644 (file)
@@ -191,7 +191,7 @@ static int tvc_probe_pdata(struct platform_device *pdev)
        in = omap_dss_find_output(pdata->source);
        if (in == NULL) {
                dev_err(&pdev->dev, "Failed to find video source\n");
-               return -ENODEV;
+               return -EPROBE_DEFER;
        }
 
        ddata->in = in;
index bc5f8ceda371b1b26308db7c644c6913445c8b18..63d88ee6dfe410469215455795bd4b63b031a040 100644 (file)
@@ -263,7 +263,7 @@ static int dvic_probe_pdata(struct platform_device *pdev)
        in = omap_dss_find_output(pdata->source);
        if (in == NULL) {
                dev_err(&pdev->dev, "Failed to find video source\n");
-               return -ENODEV;
+               return -EPROBE_DEFER;
        }
 
        ddata->in = in;
index c5826716d6abbb8b28e85ccd1d70aaa8c0058b44..9abe2c039ae9c44f0ea2cb2a3362c021e9273df4 100644 (file)
@@ -290,7 +290,7 @@ static int hdmic_probe_pdata(struct platform_device *pdev)
        in = omap_dss_find_output(pdata->source);
        if (in == NULL) {
                dev_err(&pdev->dev, "Failed to find video source\n");
-               return -ENODEV;
+               return -EPROBE_DEFER;
        }
 
        ddata->in = in;
index 02a7340111dfbf4b856122aae670bdbff2c34150..477975009eee87e89c34cc773e2d5a8818f918d6 100644 (file)
@@ -3691,6 +3691,7 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
        }
 
        pm_runtime_enable(&pdev->dev);
+       pm_runtime_irq_safe(&pdev->dev);
 
        r = dispc_runtime_get();
        if (r)
index 47ca86c5c6c0b3d1d609a001210e5eb132616076..d838ba829459400acc86388cbeda1bab77f57b24 100644 (file)
@@ -1336,14 +1336,7 @@ static int s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
                        (info->var.bits_per_pixel * info->var.xres_virtual);
        if (info->var.yres_virtual < info->var.yres) {
                dev_err(info->device, "virtual vertical size smaller than real\n");
-               goto err_find_mode;
-       }
-
-       /* maximize virtual vertical size for fast scrolling */
-       info->var.yres_virtual = info->fix.smem_len * 8 /
-                       (info->var.bits_per_pixel * info->var.xres_virtual);
-       if (info->var.yres_virtual < info->var.yres) {
-               dev_err(info->device, "virtual vertical size smaller than real\n");
+               rc = -EINVAL;
                goto err_find_mode;
        }
 
index a50c6e3a7cc4824db07f43e84732ee64a58b65cb..b232908a61925724bb61bc0f8a09ecbca6b753e6 100644 (file)
@@ -398,8 +398,6 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
        if (nr_pages > ARRAY_SIZE(frame_list))
                nr_pages = ARRAY_SIZE(frame_list);
 
-       scratch_page = get_balloon_scratch_page();
-
        for (i = 0; i < nr_pages; i++) {
                page = alloc_page(gfp);
                if (page == NULL) {
@@ -413,6 +411,12 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
 
                scrub_page(page);
 
+               /*
+                * Ballooned out frames are effectively replaced with
+                * a scratch frame.  Ensure direct mappings and the
+                * p2m are consistent.
+                */
+               scratch_page = get_balloon_scratch_page();
 #ifdef CONFIG_XEN_HAVE_PVMMU
                if (xen_pv_domain() && !PageHighMem(page)) {
                        ret = HYPERVISOR_update_va_mapping(
@@ -422,24 +426,19 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
                        BUG_ON(ret);
                }
 #endif
-       }
-
-       /* Ensure that ballooned highmem pages don't have kmaps. */
-       kmap_flush_unused();
-       flush_tlb_all();
-
-       /* No more mappings: invalidate P2M and add to balloon. */
-       for (i = 0; i < nr_pages; i++) {
-               pfn = mfn_to_pfn(frame_list[i]);
                if (!xen_feature(XENFEAT_auto_translated_physmap)) {
                        unsigned long p;
                        p = page_to_pfn(scratch_page);
                        __set_phys_to_machine(pfn, pfn_to_mfn(p));
                }
+               put_balloon_scratch_page();
+
                balloon_append(pfn_to_page(pfn));
        }
 
-       put_balloon_scratch_page();
+       /* Ensure that ballooned highmem pages don't have kmaps. */
+       kmap_flush_unused();
+       flush_tlb_all();
 
        set_xen_guest_handle(reservation.extent_start, frame_list);
        reservation.nr_extents   = nr_pages;
index 58e6cbce4156fb37a9820297e3a35c83d3524e81..08f2e1e9a7e6a4b66d08ea92e5ddf834dcb9d4a4 100644 (file)
@@ -603,10 +603,11 @@ static int v9fs_cache_register(void)
        if (ret < 0)
                return ret;
 #ifdef CONFIG_9P_FSCACHE
-       return fscache_register_netfs(&v9fs_cache_netfs);
-#else
-       return ret;
+       ret = fscache_register_netfs(&v9fs_cache_netfs);
+       if (ret < 0)
+               v9fs_destroy_inode_cache();
 #endif
+       return ret;
 }
 
 static void v9fs_cache_unregister(void)
index 53687bbf2296f8b799583786b16b59a574369f9e..a7c481402c4654416106d22d1ed7d85f65f6f8e1 100644 (file)
@@ -267,14 +267,8 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
        }
 
        /* Only creates */
-       if (!(flags & O_CREAT))
+       if (!(flags & O_CREAT) || dentry->d_inode)
                return  finish_no_open(file, res);
-       else if (dentry->d_inode) {
-               if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
-                       return -EEXIST;
-               else
-                       return finish_no_open(file, res);
-       }
 
        v9ses = v9fs_inode2v9ses(dir);
 
index 646337dc5201e702227309cc17db99f96af99173..529300327f4574d2dc36345be3c7398442548e08 100644 (file)
@@ -600,9 +600,6 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
 
        /* lock down the parent dentry so we can peer at it */
        parent = dget_parent(dentry);
-       if (!parent->d_inode)
-               goto out_bad;
-
        dir = AFS_FS_I(parent->d_inode);
 
        /* validate the parent directory */
index 6b868f0e0c4c019c3b68712ca230deb979711a98..067e3d340c353e614787fe5dbdb205dedb7b9ec4 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -167,10 +167,25 @@ static int __init aio_setup(void)
 }
 __initcall(aio_setup);
 
+static void put_aio_ring_file(struct kioctx *ctx)
+{
+       struct file *aio_ring_file = ctx->aio_ring_file;
+       if (aio_ring_file) {
+               truncate_setsize(aio_ring_file->f_inode, 0);
+
+               /* Prevent further access to the kioctx from migratepages */
+               spin_lock(&aio_ring_file->f_inode->i_mapping->private_lock);
+               aio_ring_file->f_inode->i_mapping->private_data = NULL;
+               ctx->aio_ring_file = NULL;
+               spin_unlock(&aio_ring_file->f_inode->i_mapping->private_lock);
+
+               fput(aio_ring_file);
+       }
+}
+
 static void aio_free_ring(struct kioctx *ctx)
 {
        int i;
-       struct file *aio_ring_file = ctx->aio_ring_file;
 
        for (i = 0; i < ctx->nr_pages; i++) {
                pr_debug("pid(%d) [%d] page->count=%d\n", current->pid, i,
@@ -178,14 +193,10 @@ static void aio_free_ring(struct kioctx *ctx)
                put_page(ctx->ring_pages[i]);
        }
 
+       put_aio_ring_file(ctx);
+
        if (ctx->ring_pages && ctx->ring_pages != ctx->internal_pages)
                kfree(ctx->ring_pages);
-
-       if (aio_ring_file) {
-               truncate_setsize(aio_ring_file->f_inode, 0);
-               fput(aio_ring_file);
-               ctx->aio_ring_file = NULL;
-       }
 }
 
 static int aio_ring_mmap(struct file *file, struct vm_area_struct *vma)
@@ -207,9 +218,8 @@ static int aio_set_page_dirty(struct page *page)
 static int aio_migratepage(struct address_space *mapping, struct page *new,
                        struct page *old, enum migrate_mode mode)
 {
-       struct kioctx *ctx = mapping->private_data;
+       struct kioctx *ctx;
        unsigned long flags;
-       unsigned idx = old->index;
        int rc;
 
        /* Writeback must be complete */
@@ -224,10 +234,23 @@ static int aio_migratepage(struct address_space *mapping, struct page *new,
 
        get_page(new);
 
-       spin_lock_irqsave(&ctx->completion_lock, flags);
-       migrate_page_copy(new, old);
-       ctx->ring_pages[idx] = new;
-       spin_unlock_irqrestore(&ctx->completion_lock, flags);
+       /* We can potentially race against kioctx teardown here.  Use the
+        * address_space's private data lock to protect the mapping's
+        * private_data.
+        */
+       spin_lock(&mapping->private_lock);
+       ctx = mapping->private_data;
+       if (ctx) {
+               pgoff_t idx;
+               spin_lock_irqsave(&ctx->completion_lock, flags);
+               migrate_page_copy(new, old);
+               idx = old->index;
+               if (idx < (pgoff_t)ctx->nr_pages)
+                       ctx->ring_pages[idx] = new;
+               spin_unlock_irqrestore(&ctx->completion_lock, flags);
+       } else
+               rc = -EBUSY;
+       spin_unlock(&mapping->private_lock);
 
        return rc;
 }
@@ -617,8 +640,7 @@ out_freepcpu:
 out_freeref:
        free_percpu(ctx->users.pcpu_count);
 out_freectx:
-       if (ctx->aio_ring_file)
-               fput(ctx->aio_ring_file);
+       put_aio_ring_file(ctx);
        kmem_cache_free(kioctx_cachep, ctx);
        pr_debug("error allocating ioctx %d\n", err);
        return ERR_PTR(err);
index 3db70dae40d3a842de562c9fb4e26c29f9284239..689e40d983ad64ca3726cd5f8dd64c44d49bb5e6 100644 (file)
@@ -109,13 +109,7 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
 
        pkt.hdr.proto_version = sbi->version;
        pkt.hdr.type = type;
-       mutex_lock(&sbi->wq_mutex);
 
-       /* Check if we have become catatonic */
-       if (sbi->catatonic) {
-               mutex_unlock(&sbi->wq_mutex);
-               return;
-       }
        switch (type) {
        /* Kernel protocol v4 missing and expire packets */
        case autofs_ptype_missing:
@@ -427,7 +421,6 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
                wq->tgid = current->tgid;
                wq->status = -EINTR; /* Status return if interrupted */
                wq->wait_ctr = 2;
-               mutex_unlock(&sbi->wq_mutex);
 
                if (sbi->version < 5) {
                        if (notify == NFY_MOUNT)
@@ -449,15 +442,15 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
                        (unsigned long) wq->wait_queue_token, wq->name.len,
                        wq->name.name, notify);
 
-               /* autofs4_notify_daemon() may block */
+               /* autofs4_notify_daemon() may block; it will unlock ->wq_mutex */
                autofs4_notify_daemon(sbi, wq, type);
        } else {
                wq->wait_ctr++;
-               mutex_unlock(&sbi->wq_mutex);
-               kfree(qstr.name);
                DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
                        (unsigned long) wq->wait_queue_token, wq->name.len,
                        wq->name.name, notify);
+               mutex_unlock(&sbi->wq_mutex);
+               kfree(qstr.name);
        }
 
        /*
index 100edcc5e3122323eb8f4087305e623c666eceb0..4c94a79991bb6d8ae0d2e12ae8c647e2fe22f7fe 100644 (file)
@@ -1413,7 +1413,7 @@ static void fill_siginfo_note(struct memelfnote *note, user_siginfo_t *csigdata,
  *   long file_ofs
  * followed by COUNT filenames in ASCII: "FILE1" NUL "FILE2" NUL...
  */
-static void fill_files_note(struct memelfnote *note)
+static int fill_files_note(struct memelfnote *note)
 {
        struct vm_area_struct *vma;
        unsigned count, size, names_ofs, remaining, n;
@@ -1428,11 +1428,11 @@ static void fill_files_note(struct memelfnote *note)
        names_ofs = (2 + 3 * count) * sizeof(data[0]);
  alloc:
        if (size >= MAX_FILE_NOTE_SIZE) /* paranoia check */
-               goto err;
+               return -EINVAL;
        size = round_up(size, PAGE_SIZE);
        data = vmalloc(size);
        if (!data)
-               goto err;
+               return -ENOMEM;
 
        start_end_ofs = data + 2;
        name_base = name_curpos = ((char *)data) + names_ofs;
@@ -1485,7 +1485,7 @@ static void fill_files_note(struct memelfnote *note)
 
        size = name_curpos - (char *)data;
        fill_note(note, "CORE", NT_FILE, size, data);
err: ;
      return 0;
 }
 
 #ifdef CORE_DUMP_USE_REGSET
@@ -1686,8 +1686,8 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
        fill_auxv_note(&info->auxv, current->mm);
        info->size += notesize(&info->auxv);
 
-       fill_files_note(&info->files);
-       info->size += notesize(&info->files);
+       if (fill_files_note(&info->files) == 0)
+               info->size += notesize(&info->files);
 
        return 1;
 }
@@ -1719,7 +1719,8 @@ static int write_note_info(struct elf_note_info *info,
                        return 0;
                if (first && !writenote(&info->auxv, file, foffset))
                        return 0;
-               if (first && !writenote(&info->files, file, foffset))
+               if (first && info->files.data &&
+                               !writenote(&info->files, file, foffset))
                        return 0;
 
                for (i = 1; i < info->thread_notes; ++i)
@@ -1806,6 +1807,7 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
 
 struct elf_note_info {
        struct memelfnote *notes;
+       struct memelfnote *notes_files;
        struct elf_prstatus *prstatus;  /* NT_PRSTATUS */
        struct elf_prpsinfo *psinfo;    /* NT_PRPSINFO */
        struct list_head thread_list;
@@ -1896,9 +1898,12 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
 
        fill_siginfo_note(info->notes + 2, &info->csigdata, siginfo);
        fill_auxv_note(info->notes + 3, current->mm);
-       fill_files_note(info->notes + 4);
+       info->numnote = 4;
 
-       info->numnote = 5;
+       if (fill_files_note(info->notes + info->numnote) == 0) {
+               info->notes_files = info->notes + info->numnote;
+               info->numnote++;
+       }
 
        /* Try to dump the FPU. */
        info->prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, regs,
@@ -1960,8 +1965,9 @@ static void free_note_info(struct elf_note_info *info)
                kfree(list_entry(tmp, struct elf_thread_status, list));
        }
 
-       /* Free data allocated by fill_files_note(): */
-       vfree(info->notes[4].data);
+       /* Free data possibly allocated by fill_files_note(): */
+       if (info->notes_files)
+               vfree(info->notes_files->data);
 
        kfree(info->prstatus);
        kfree(info->psinfo);
@@ -2044,7 +2050,7 @@ static int elf_core_dump(struct coredump_params *cprm)
        struct vm_area_struct *vma, *gate_vma;
        struct elfhdr *elf = NULL;
        loff_t offset = 0, dataoff, foffset;
-       struct elf_note_info info;
+       struct elf_note_info info = { };
        struct elf_phdr *phdr4note = NULL;
        struct elf_shdr *shdr4extnum = NULL;
        Elf_Half e_phnum;
index 60250847929fcd0421e5d72b9655bbe4c3a785e1..fc60b31453eefbbdcc234c7df78c5504da655980 100644 (file)
@@ -735,7 +735,7 @@ void bioset_integrity_free(struct bio_set *bs)
                mempool_destroy(bs->bio_integrity_pool);
 
        if (bs->bvec_integrity_pool)
-               mempool_destroy(bs->bio_integrity_pool);
+               mempool_destroy(bs->bvec_integrity_pool);
 }
 EXPORT_SYMBOL(bioset_integrity_free);
 
index b3b20ed9510e5ccc285195cce7aa7e3f524ed063..ea5035da4d9a0cd9fd6f5f657bb01272c63175c3 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -917,8 +917,8 @@ void bio_copy_data(struct bio *dst, struct bio *src)
                src_p = kmap_atomic(src_bv->bv_page);
                dst_p = kmap_atomic(dst_bv->bv_page);
 
-               memcpy(dst_p + dst_bv->bv_offset,
-                      src_p + src_bv->bv_offset,
+               memcpy(dst_p + dst_offset,
+                      src_p + src_offset,
                       bytes);
 
                kunmap_atomic(dst_p);
index 58b7d14b08ee1d47ec66a06243ee16f63854b676..08cc08f037a633199bffb3fadfa95750302eb25e 100644 (file)
@@ -107,7 +107,8 @@ static void check_idle_worker(struct btrfs_worker_thread *worker)
                worker->idle = 1;
 
                /* the list may be empty if the worker is just starting */
-               if (!list_empty(&worker->worker_list)) {
+               if (!list_empty(&worker->worker_list) &&
+                   !worker->workers->stopping) {
                        list_move(&worker->worker_list,
                                 &worker->workers->idle_list);
                }
@@ -127,7 +128,8 @@ static void check_busy_worker(struct btrfs_worker_thread *worker)
                spin_lock_irqsave(&worker->workers->lock, flags);
                worker->idle = 0;
 
-               if (!list_empty(&worker->worker_list)) {
+               if (!list_empty(&worker->worker_list) &&
+                   !worker->workers->stopping) {
                        list_move_tail(&worker->worker_list,
                                      &worker->workers->worker_list);
                }
@@ -412,6 +414,7 @@ void btrfs_stop_workers(struct btrfs_workers *workers)
        int can_stop;
 
        spin_lock_irq(&workers->lock);
+       workers->stopping = 1;
        list_splice_init(&workers->idle_list, &workers->worker_list);
        while (!list_empty(&workers->worker_list)) {
                cur = workers->worker_list.next;
@@ -455,6 +458,7 @@ void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max,
        workers->ordered = 0;
        workers->atomic_start_pending = 0;
        workers->atomic_worker_start = async_helper;
+       workers->stopping = 0;
 }
 
 /*
@@ -480,15 +484,19 @@ static int __btrfs_start_workers(struct btrfs_workers *workers)
        atomic_set(&worker->num_pending, 0);
        atomic_set(&worker->refs, 1);
        worker->workers = workers;
-       worker->task = kthread_run(worker_loop, worker,
-                                  "btrfs-%s-%d", workers->name,
-                                  workers->num_workers + 1);
+       worker->task = kthread_create(worker_loop, worker,
+                                     "btrfs-%s-%d", workers->name,
+                                     workers->num_workers + 1);
        if (IS_ERR(worker->task)) {
                ret = PTR_ERR(worker->task);
-               kfree(worker);
                goto fail;
        }
+
        spin_lock_irq(&workers->lock);
+       if (workers->stopping) {
+               spin_unlock_irq(&workers->lock);
+               goto fail_kthread;
+       }
        list_add_tail(&worker->worker_list, &workers->idle_list);
        worker->idle = 1;
        workers->num_workers++;
@@ -496,8 +504,13 @@ static int __btrfs_start_workers(struct btrfs_workers *workers)
        WARN_ON(workers->num_workers_starting < 0);
        spin_unlock_irq(&workers->lock);
 
+       wake_up_process(worker->task);
        return 0;
+
+fail_kthread:
+       kthread_stop(worker->task);
 fail:
+       kfree(worker);
        spin_lock_irq(&workers->lock);
        workers->num_workers_starting--;
        spin_unlock_irq(&workers->lock);
index 063698b90ce2dd0481663aeee46b30ef796d52e2..1f26792683edf195b48db80992c05acae6fd71f0 100644 (file)
@@ -107,6 +107,8 @@ struct btrfs_workers {
 
        /* extra name for this worker, used for current->name */
        char *name;
+
+       int stopping;
 };
 
 void btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work);
index d0ae226926ee2d2f43d29220da8fd531f31e8687..71f074e1870b2e9fe183cf338ad2515314155e6e 100644 (file)
@@ -213,7 +213,10 @@ static inline bool btrfs_is_free_space_inode(struct inode *inode)
 static inline int btrfs_inode_in_log(struct inode *inode, u64 generation)
 {
        if (BTRFS_I(inode)->logged_trans == generation &&
-           BTRFS_I(inode)->last_sub_trans <= BTRFS_I(inode)->last_log_commit)
+           BTRFS_I(inode)->last_sub_trans <=
+           BTRFS_I(inode)->last_log_commit &&
+           BTRFS_I(inode)->last_sub_trans <=
+           BTRFS_I(inode)->root->last_log_commit)
                return 1;
        return 0;
 }
index 64346721173f24f31170a8e70e85f7d49a83b609..61b5bcd57b7e320624c2778d2051db03b79f2282 100644 (file)
@@ -1005,8 +1005,11 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
                return ret;
        }
 
-       if (root->ref_cows)
-               btrfs_reloc_cow_block(trans, root, buf, cow);
+       if (root->ref_cows) {
+               ret = btrfs_reloc_cow_block(trans, root, buf, cow);
+               if (ret)
+                       return ret;
+       }
 
        if (buf == root->node) {
                WARN_ON(parent && parent != buf);
index 3c1da6f98a4d25666f4a2afb6fce25bff80ac8c8..0506f40ede8331f8ab7b20a4d2778e49c886fe91 100644 (file)
@@ -1118,15 +1118,6 @@ struct btrfs_space_info {
         */
        struct percpu_counter total_bytes_pinned;
 
-       /*
-        * we bump reservation progress every time we decrement
-        * bytes_reserved.  This way people waiting for reservations
-        * know something good has happened and they can check
-        * for progress.  The number here isn't to be trusted, it
-        * just shows reclaim activity
-        */
-       unsigned long reservation_progress;
-
        unsigned int full:1;    /* indicates that we cannot allocate any more
                                   chunks for this space */
        unsigned int chunk_alloc:1;     /* set if we are allocating a chunk */
@@ -3135,7 +3126,7 @@ static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_root *root,
                                                 unsigned num_items)
 {
        return (root->leafsize + root->nodesize * (BTRFS_MAX_LEVEL - 1)) *
-               3 * num_items;
+               2 * num_items;
 }
 
 /*
@@ -3939,9 +3930,9 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
                            struct btrfs_root *root);
 int btrfs_recover_relocation(struct btrfs_root *root);
 int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len);
-void btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
-                          struct btrfs_root *root, struct extent_buffer *buf,
-                          struct extent_buffer *cow);
+int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
+                         struct btrfs_root *root, struct extent_buffer *buf,
+                         struct extent_buffer *cow);
 void btrfs_reloc_pre_snapshot(struct btrfs_trans_handle *trans,
                              struct btrfs_pending_snapshot *pending,
                              u64 *bytes_to_reserve);
index a64435359385e86a483f30696c932da2c8d5bdb0..9efb94e95858e8c53cb84f587b74a064e8701dc4 100644 (file)
@@ -400,7 +400,7 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
        args->result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR;
        btrfs_dev_replace_unlock(dev_replace);
 
-       btrfs_wait_all_ordered_extents(root->fs_info, 0);
+       btrfs_wait_all_ordered_extents(root->fs_info);
 
        /* force writing the updated state information to disk */
        trans = btrfs_start_transaction(root, 0);
@@ -475,7 +475,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
                mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
                return ret;
        }
-       btrfs_wait_all_ordered_extents(root->fs_info, 0);
+       btrfs_wait_all_ordered_extents(root->fs_info);
 
        trans = btrfs_start_transaction(root, 0);
        if (IS_ERR(trans)) {
@@ -535,10 +535,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
        list_add(&tgt_device->dev_alloc_list, &fs_info->fs_devices->alloc_list);
 
        btrfs_rm_dev_replace_srcdev(fs_info, src_device);
-       if (src_device->bdev) {
-               /* zero out the old super */
-               btrfs_scratch_superblock(src_device);
-       }
+
        /*
         * this is again a consistent state where no dev_replace procedure
         * is running, the target device is part of the filesystem, the
index 4cbb00af92ff3bed86561b9f02ec6fbcc04665b2..4ae17ed13b3274f228c8879383ec5124ca5f05dd 100644 (file)
@@ -157,6 +157,7 @@ static struct btrfs_lockdep_keyset {
        { .id = BTRFS_TREE_LOG_OBJECTID,        .name_stem = "log"      },
        { .id = BTRFS_TREE_RELOC_OBJECTID,      .name_stem = "treloc"   },
        { .id = BTRFS_DATA_RELOC_TREE_OBJECTID, .name_stem = "dreloc"   },
+       { .id = BTRFS_UUID_TREE_OBJECTID,       .name_stem = "uuid"     },
        { .id = 0,                              .name_stem = "tree"     },
 };
 
@@ -3415,6 +3416,7 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors)
        if (total_errors > max_errors) {
                printk(KERN_ERR "btrfs: %d errors while writing supers\n",
                       total_errors);
+               mutex_unlock(&root->fs_info->fs_devices->device_list_mutex);
 
                /* FUA is masked off if unsupported and can't be the reason */
                btrfs_error(root->fs_info, -EIO,
index cfb3cf711b34d6555afed3d21dd16480c662cc55..d58bef130a41984ac7e3172aad43eb87547af64b 100644 (file)
@@ -3925,7 +3925,6 @@ static int can_overcommit(struct btrfs_root *root,
        u64 space_size;
        u64 avail;
        u64 used;
-       u64 to_add;
 
        used = space_info->bytes_used + space_info->bytes_reserved +
                space_info->bytes_pinned + space_info->bytes_readonly;
@@ -3959,25 +3958,17 @@ static int can_overcommit(struct btrfs_root *root,
                       BTRFS_BLOCK_GROUP_RAID10))
                avail >>= 1;
 
-       to_add = space_info->total_bytes;
-
        /*
         * If we aren't flushing all things, let us overcommit up to
         * 1/2th of the space. If we can flush, don't let us overcommit
         * too much, let it overcommit up to 1/8 of the space.
         */
        if (flush == BTRFS_RESERVE_FLUSH_ALL)
-               to_add >>= 3;
+               avail >>= 3;
        else
-               to_add >>= 1;
-
-       /*
-        * Limit the overcommit to the amount of free space we could possibly
-        * allocate for chunks.
-        */
-       to_add = min(avail, to_add);
+               avail >>= 1;
 
-       if (used + bytes < space_info->total_bytes + to_add)
+       if (used + bytes < space_info->total_bytes + avail)
                return 1;
        return 0;
 }
@@ -4000,7 +3991,7 @@ static void btrfs_writeback_inodes_sb_nr(struct btrfs_root *root,
                 */
                btrfs_start_all_delalloc_inodes(root->fs_info, 0);
                if (!current->journal_info)
-                       btrfs_wait_all_ordered_extents(root->fs_info, 0);
+                       btrfs_wait_all_ordered_extents(root->fs_info);
        }
 }
 
@@ -4030,7 +4021,7 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig,
        if (delalloc_bytes == 0) {
                if (trans)
                        return;
-               btrfs_wait_all_ordered_extents(root->fs_info, 0);
+               btrfs_wait_all_ordered_extents(root->fs_info);
                return;
        }
 
@@ -4058,7 +4049,7 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig,
 
                loops++;
                if (wait_ordered && !trans) {
-                       btrfs_wait_all_ordered_extents(root->fs_info, 0);
+                       btrfs_wait_all_ordered_extents(root->fs_info);
                } else {
                        time_left = schedule_timeout_killable(1);
                        if (time_left)
@@ -4465,7 +4456,6 @@ static void block_rsv_release_bytes(struct btrfs_fs_info *fs_info,
                        space_info->bytes_may_use -= num_bytes;
                        trace_btrfs_space_reservation(fs_info, "space_info",
                                        space_info->flags, num_bytes, 0);
-                       space_info->reservation_progress++;
                        spin_unlock(&space_info->lock);
                }
        }
@@ -4666,7 +4656,6 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
                sinfo->bytes_may_use -= num_bytes;
                trace_btrfs_space_reservation(fs_info, "space_info",
                                      sinfo->flags, num_bytes, 0);
-               sinfo->reservation_progress++;
                block_rsv->reserved = block_rsv->size;
                block_rsv->full = 1;
        }
@@ -5446,7 +5435,6 @@ static int btrfs_update_reserved_bytes(struct btrfs_block_group_cache *cache,
                        space_info->bytes_readonly += num_bytes;
                cache->reserved -= num_bytes;
                space_info->bytes_reserved -= num_bytes;
-               space_info->reservation_progress++;
        }
        spin_unlock(&cache->lock);
        spin_unlock(&space_info->lock);
@@ -6117,10 +6105,13 @@ enum btrfs_loop_type {
 /*
  * walks the btree of allocated extents and find a hole of a given size.
  * The key ins is changed to record the hole:
- * ins->objectid == block start
+ * ins->objectid == start position
  * ins->flags = BTRFS_EXTENT_ITEM_KEY
- * ins->offset == number of blocks
+ * ins->offset == the size of the hole.
  * Any available blocks before search_start are skipped.
+ *
+ * If there is no suitable free space, we will record the max size of
+ * the free space extent currently.
  */
 static noinline int find_free_extent(struct btrfs_root *orig_root,
                                     u64 num_bytes, u64 empty_size,
@@ -6133,6 +6124,7 @@ static noinline int find_free_extent(struct btrfs_root *orig_root,
        struct btrfs_block_group_cache *block_group = NULL;
        struct btrfs_block_group_cache *used_block_group;
        u64 search_start = 0;
+       u64 max_extent_size = 0;
        int empty_cluster = 2 * 1024 * 1024;
        struct btrfs_space_info *space_info;
        int loop = 0;
@@ -6292,7 +6284,10 @@ have_block_group:
                                btrfs_get_block_group(used_block_group);
 
                        offset = btrfs_alloc_from_cluster(used_block_group,
-                         last_ptr, num_bytes, used_block_group->key.objectid);
+                                               last_ptr,
+                                               num_bytes,
+                                               used_block_group->key.objectid,
+                                               &max_extent_size);
                        if (offset) {
                                /* we have a block, we're done */
                                spin_unlock(&last_ptr->refill_lock);
@@ -6355,8 +6350,10 @@ refill_cluster:
                                 * cluster
                                 */
                                offset = btrfs_alloc_from_cluster(block_group,
-                                                 last_ptr, num_bytes,
-                                                 search_start);
+                                                       last_ptr,
+                                                       num_bytes,
+                                                       search_start,
+                                                       &max_extent_size);
                                if (offset) {
                                        /* we found one, proceed */
                                        spin_unlock(&last_ptr->refill_lock);
@@ -6391,13 +6388,18 @@ unclustered_alloc:
                if (cached &&
                    block_group->free_space_ctl->free_space <
                    num_bytes + empty_cluster + empty_size) {
+                       if (block_group->free_space_ctl->free_space >
+                           max_extent_size)
+                               max_extent_size =
+                                       block_group->free_space_ctl->free_space;
                        spin_unlock(&block_group->free_space_ctl->tree_lock);
                        goto loop;
                }
                spin_unlock(&block_group->free_space_ctl->tree_lock);
 
                offset = btrfs_find_space_for_alloc(block_group, search_start,
-                                                   num_bytes, empty_size);
+                                                   num_bytes, empty_size,
+                                                   &max_extent_size);
                /*
                 * If we didn't find a chunk, and we haven't failed on this
                 * block group before, and this block group is in the middle of
@@ -6515,7 +6517,8 @@ loop:
                ret = 0;
        }
 out:
-
+       if (ret == -ENOSPC)
+               ins->offset = max_extent_size;
        return ret;
 }
 
@@ -6573,8 +6576,8 @@ again:
                               flags);
 
        if (ret == -ENOSPC) {
-               if (!final_tried) {
-                       num_bytes = num_bytes >> 1;
+               if (!final_tried && ins->offset) {
+                       num_bytes = min(num_bytes >> 1, ins->offset);
                        num_bytes = round_down(num_bytes, root->sectorsize);
                        num_bytes = max(num_bytes, min_alloc_size);
                        if (num_bytes == min_alloc_size)
index 09582b81640cc8e02ced7ea7c8ec6b22acdc8dba..22bda32acb893a09aa0a0472d8ab78c20c12fbdb 100644 (file)
@@ -145,8 +145,16 @@ int __init extent_io_init(void)
                                     offsetof(struct btrfs_io_bio, bio));
        if (!btrfs_bioset)
                goto free_buffer_cache;
+
+       if (bioset_integrity_create(btrfs_bioset, BIO_POOL_SIZE))
+               goto free_bioset;
+
        return 0;
 
+free_bioset:
+       bioset_free(btrfs_bioset);
+       btrfs_bioset = NULL;
+
 free_buffer_cache:
        kmem_cache_destroy(extent_buffer_cache);
        extent_buffer_cache = NULL;
@@ -1481,10 +1489,12 @@ static noinline u64 find_delalloc_range(struct extent_io_tree *tree,
                *end = state->end;
                cur_start = state->end + 1;
                node = rb_next(node);
-               if (!node)
-                       break;
                total_bytes += state->end - state->start + 1;
-               if (total_bytes >= max_bytes)
+               if (total_bytes >= max_bytes) {
+                       *end = *start + max_bytes - 1;
+                       break;
+               }
+               if (!node)
                        break;
        }
 out:
@@ -1612,7 +1622,7 @@ again:
                *start = delalloc_start;
                *end = delalloc_end;
                free_extent_state(cached_state);
-               return found;
+               return 0;
        }
 
        /*
index bc5072b2db537f0f27af1851532b7417b41a8489..72da4df53c9a224d7a5106a907fc4ba4e08f5ebb 100644 (file)
@@ -1859,8 +1859,8 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 
        ret = btrfs_log_dentry_safe(trans, root, dentry);
        if (ret < 0) {
-               mutex_unlock(&inode->i_mutex);
-               goto out;
+               /* Fallthrough and commit/free transaction. */
+               ret = 1;
        }
 
        /* we've logged all the items and now have a consistent
index 3f0ddfce96e6ff2bdaaef019ea7ee00f9af070af..b4f9904c4c6b2ed5f0da30ad664baf33100a879c 100644 (file)
@@ -1431,13 +1431,19 @@ static void bitmap_set_bits(struct btrfs_free_space_ctl *ctl,
        ctl->free_space += bytes;
 }
 
+/*
+ * If we can not find suitable extent, we will use bytes to record
+ * the size of the max extent.
+ */
 static int search_bitmap(struct btrfs_free_space_ctl *ctl,
                         struct btrfs_free_space *bitmap_info, u64 *offset,
                         u64 *bytes)
 {
        unsigned long found_bits = 0;
+       unsigned long max_bits = 0;
        unsigned long bits, i;
        unsigned long next_zero;
+       unsigned long extent_bits;
 
        i = offset_to_bit(bitmap_info->offset, ctl->unit,
                          max_t(u64, *offset, bitmap_info->offset));
@@ -1446,9 +1452,12 @@ static int search_bitmap(struct btrfs_free_space_ctl *ctl,
        for_each_set_bit_from(i, bitmap_info->bitmap, BITS_PER_BITMAP) {
                next_zero = find_next_zero_bit(bitmap_info->bitmap,
                                               BITS_PER_BITMAP, i);
-               if ((next_zero - i) >= bits) {
-                       found_bits = next_zero - i;
+               extent_bits = next_zero - i;
+               if (extent_bits >= bits) {
+                       found_bits = extent_bits;
                        break;
+               } else if (extent_bits > max_bits) {
+                       max_bits = extent_bits;
                }
                i = next_zero;
        }
@@ -1459,38 +1468,41 @@ static int search_bitmap(struct btrfs_free_space_ctl *ctl,
                return 0;
        }
 
+       *bytes = (u64)(max_bits) * ctl->unit;
        return -1;
 }
 
+/* Cache the size of the max extent in bytes */
 static struct btrfs_free_space *
 find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes,
-               unsigned long align)
+               unsigned long align, u64 *max_extent_size)
 {
        struct btrfs_free_space *entry;
        struct rb_node *node;
-       u64 ctl_off;
        u64 tmp;
        u64 align_off;
        int ret;
 
        if (!ctl->free_space_offset.rb_node)
-               return NULL;
+               goto out;
 
        entry = tree_search_offset(ctl, offset_to_bitmap(ctl, *offset), 0, 1);
        if (!entry)
-               return NULL;
+               goto out;
 
        for (node = &entry->offset_index; node; node = rb_next(node)) {
                entry = rb_entry(node, struct btrfs_free_space, offset_index);
-               if (entry->bytes < *bytes)
+               if (entry->bytes < *bytes) {
+                       if (entry->bytes > *max_extent_size)
+                               *max_extent_size = entry->bytes;
                        continue;
+               }
 
                /* make sure the space returned is big enough
                 * to match our requested alignment
                 */
                if (*bytes >= align) {
-                       ctl_off = entry->offset - ctl->start;
-                       tmp = ctl_off + align - 1;;
+                       tmp = entry->offset - ctl->start + align - 1;
                        do_div(tmp, align);
                        tmp = tmp * align + ctl->start;
                        align_off = tmp - entry->offset;
@@ -1499,14 +1511,22 @@ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes,
                        tmp = entry->offset;
                }
 
-               if (entry->bytes < *bytes + align_off)
+               if (entry->bytes < *bytes + align_off) {
+                       if (entry->bytes > *max_extent_size)
+                               *max_extent_size = entry->bytes;
                        continue;
+               }
 
                if (entry->bitmap) {
-                       ret = search_bitmap(ctl, entry, &tmp, bytes);
+                       u64 size = *bytes;
+
+                       ret = search_bitmap(ctl, entry, &tmp, &size);
                        if (!ret) {
                                *offset = tmp;
+                               *bytes = size;
                                return entry;
+                       } else if (size > *max_extent_size) {
+                               *max_extent_size = size;
                        }
                        continue;
                }
@@ -1515,7 +1535,7 @@ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes,
                *bytes = entry->bytes - align_off;
                return entry;
        }
-
+out:
        return NULL;
 }
 
@@ -2116,7 +2136,8 @@ void btrfs_remove_free_space_cache(struct btrfs_block_group_cache *block_group)
 }
 
 u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group,
-                              u64 offset, u64 bytes, u64 empty_size)
+                              u64 offset, u64 bytes, u64 empty_size,
+                              u64 *max_extent_size)
 {
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *entry = NULL;
@@ -2127,7 +2148,7 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group,
 
        spin_lock(&ctl->tree_lock);
        entry = find_free_space(ctl, &offset, &bytes_search,
-                               block_group->full_stripe_len);
+                               block_group->full_stripe_len, max_extent_size);
        if (!entry)
                goto out;
 
@@ -2137,7 +2158,6 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group,
                if (!entry->bytes)
                        free_bitmap(ctl, entry);
        } else {
-
                unlink_free_space(ctl, entry);
                align_gap_len = offset - entry->offset;
                align_gap = entry->offset;
@@ -2151,7 +2171,6 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group,
                else
                        link_free_space(ctl, entry);
        }
-
 out:
        spin_unlock(&ctl->tree_lock);
 
@@ -2206,7 +2225,8 @@ int btrfs_return_cluster_to_free_space(
 static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group,
                                   struct btrfs_free_cluster *cluster,
                                   struct btrfs_free_space *entry,
-                                  u64 bytes, u64 min_start)
+                                  u64 bytes, u64 min_start,
+                                  u64 *max_extent_size)
 {
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        int err;
@@ -2218,8 +2238,11 @@ static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group,
        search_bytes = bytes;
 
        err = search_bitmap(ctl, entry, &search_start, &search_bytes);
-       if (err)
+       if (err) {
+               if (search_bytes > *max_extent_size)
+                       *max_extent_size = search_bytes;
                return 0;
+       }
 
        ret = search_start;
        __bitmap_clear_bits(ctl, entry, ret, bytes);
@@ -2234,7 +2257,7 @@ static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group,
  */
 u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group,
                             struct btrfs_free_cluster *cluster, u64 bytes,
-                            u64 min_start)
+                            u64 min_start, u64 *max_extent_size)
 {
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *entry = NULL;
@@ -2254,6 +2277,9 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group,
 
        entry = rb_entry(node, struct btrfs_free_space, offset_index);
        while(1) {
+               if (entry->bytes < bytes && entry->bytes > *max_extent_size)
+                       *max_extent_size = entry->bytes;
+
                if (entry->bytes < bytes ||
                    (!entry->bitmap && entry->offset < min_start)) {
                        node = rb_next(&entry->offset_index);
@@ -2267,7 +2293,8 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group,
                if (entry->bitmap) {
                        ret = btrfs_alloc_from_bitmap(block_group,
                                                      cluster, entry, bytes,
-                                                     cluster->window_start);
+                                                     cluster->window_start,
+                                                     max_extent_size);
                        if (ret == 0) {
                                node = rb_next(&entry->offset_index);
                                if (!node)
index c7490416747656e1f3f119c5dc4f91cbf315e2ca..e737f92cf6d0b69ffbcc1e94882abc8693c3e3a5 100644 (file)
@@ -94,7 +94,8 @@ void __btrfs_remove_free_space_cache(struct btrfs_free_space_ctl *ctl);
 void btrfs_remove_free_space_cache(struct btrfs_block_group_cache
                                     *block_group);
 u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group,
-                              u64 offset, u64 bytes, u64 empty_size);
+                              u64 offset, u64 bytes, u64 empty_size,
+                              u64 *max_extent_size);
 u64 btrfs_find_ino_for_alloc(struct btrfs_root *fs_root);
 void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group,
                           u64 bytes);
@@ -105,7 +106,7 @@ int btrfs_find_space_cluster(struct btrfs_root *root,
 void btrfs_init_free_cluster(struct btrfs_free_cluster *cluster);
 u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group,
                             struct btrfs_free_cluster *cluster, u64 bytes,
-                            u64 min_start);
+                            u64 min_start, u64 *max_extent_size);
 int btrfs_return_cluster_to_free_space(
                               struct btrfs_block_group_cache *block_group,
                               struct btrfs_free_cluster *cluster);
index f338c5672d583a27dddc37c5e217fa6a8995e271..22ebc13b6c992a0755513253e17f9dd7f20b9706 100644 (file)
@@ -4688,11 +4688,11 @@ static void inode_tree_add(struct inode *inode)
        struct btrfs_inode *entry;
        struct rb_node **p;
        struct rb_node *parent;
+       struct rb_node *new = &BTRFS_I(inode)->rb_node;
        u64 ino = btrfs_ino(inode);
 
        if (inode_unhashed(inode))
                return;
-again:
        parent = NULL;
        spin_lock(&root->inode_lock);
        p = &root->inode_tree.rb_node;
@@ -4707,14 +4707,14 @@ again:
                else {
                        WARN_ON(!(entry->vfs_inode.i_state &
                                  (I_WILL_FREE | I_FREEING)));
-                       rb_erase(parent, &root->inode_tree);
+                       rb_replace_node(parent, new, &root->inode_tree);
                        RB_CLEAR_NODE(parent);
                        spin_unlock(&root->inode_lock);
-                       goto again;
+                       return;
                }
        }
-       rb_link_node(&BTRFS_I(inode)->rb_node, parent, p);
-       rb_insert_color(&BTRFS_I(inode)->rb_node, &root->inode_tree);
+       rb_link_node(new, parent, p);
+       rb_insert_color(new, &root->inode_tree);
        spin_unlock(&root->inode_lock);
 }
 
@@ -8216,6 +8216,10 @@ static int __start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
 
                work = btrfs_alloc_delalloc_work(inode, 0, delay_iput);
                if (unlikely(!work)) {
+                       if (delay_iput)
+                               btrfs_add_delayed_iput(inode);
+                       else
+                               iput(inode);
                        ret = -ENOMEM;
                        goto out;
                }
@@ -8613,11 +8617,13 @@ static const struct inode_operations btrfs_dir_inode_operations = {
        .removexattr    = btrfs_removexattr,
        .permission     = btrfs_permission,
        .get_acl        = btrfs_get_acl,
+       .update_time    = btrfs_update_time,
 };
 static const struct inode_operations btrfs_dir_ro_inode_operations = {
        .lookup         = btrfs_lookup,
        .permission     = btrfs_permission,
        .get_acl        = btrfs_get_acl,
+       .update_time    = btrfs_update_time,
 };
 
 static const struct file_operations btrfs_dir_file_operations = {
index 1a5b9462dd9ae2639513237358c2f55662bf366f..9d46f60cb9439ab3a41ab83f2f323f13aa564590 100644 (file)
@@ -574,7 +574,7 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
        if (ret)
                return ret;
 
-       btrfs_wait_ordered_extents(root, 0);
+       btrfs_wait_ordered_extents(root);
 
        pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS);
        if (!pending_snapshot)
@@ -2696,9 +2696,9 @@ out_unlock:
 static long btrfs_ioctl_file_extent_same(struct file *file,
                                         void __user *argp)
 {
-       struct btrfs_ioctl_same_args *args = argp;
-       struct btrfs_ioctl_same_args same;
-       struct btrfs_ioctl_same_extent_info info;
+       struct btrfs_ioctl_same_args tmp;
+       struct btrfs_ioctl_same_args *same;
+       struct btrfs_ioctl_same_extent_info *info;
        struct inode *src = file->f_dentry->d_inode;
        struct file *dst_file = NULL;
        struct inode *dst;
@@ -2706,6 +2706,7 @@ static long btrfs_ioctl_file_extent_same(struct file *file,
        u64 len;
        int i;
        int ret;
+       unsigned long size;
        u64 bs = BTRFS_I(src)->root->fs_info->sb->s_blocksize;
        bool is_admin = capable(CAP_SYS_ADMIN);
 
@@ -2716,15 +2717,30 @@ static long btrfs_ioctl_file_extent_same(struct file *file,
        if (ret)
                return ret;
 
-       if (copy_from_user(&same,
+       if (copy_from_user(&tmp,
                           (struct btrfs_ioctl_same_args __user *)argp,
-                          sizeof(same))) {
+                          sizeof(tmp))) {
                ret = -EFAULT;
                goto out;
        }
 
-       off = same.logical_offset;
-       len = same.length;
+       size = sizeof(tmp) +
+               tmp.dest_count * sizeof(struct btrfs_ioctl_same_extent_info);
+
+       same = kmalloc(size, GFP_NOFS);
+       if (!same) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+       if (copy_from_user(same,
+                          (struct btrfs_ioctl_same_args __user *)argp, size)) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+       off = same->logical_offset;
+       len = same->length;
 
        /*
         * Limit the total length we will dedupe for each operation.
@@ -2752,27 +2768,28 @@ static long btrfs_ioctl_file_extent_same(struct file *file,
        if (!S_ISREG(src->i_mode))
                goto out;
 
-       ret = 0;
-       for (i = 0; i < same.dest_count; i++) {
-               if (copy_from_user(&info, &args->info[i], sizeof(info))) {
-                       ret = -EFAULT;
-                       goto out;
-               }
+       /* pre-format output fields to sane values */
+       for (i = 0; i < same->dest_count; i++) {
+               same->info[i].bytes_deduped = 0ULL;
+               same->info[i].status = 0;
+       }
 
-               info.bytes_deduped = 0;
+       ret = 0;
+       for (i = 0; i < same->dest_count; i++) {
+               info = &same->info[i];
 
-               dst_file = fget(info.fd);
+               dst_file = fget(info->fd);
                if (!dst_file) {
-                       info.status = -EBADF;
+                       info->status = -EBADF;
                        goto next;
                }
 
                if (!(is_admin || (dst_file->f_mode & FMODE_WRITE))) {
-                       info.status = -EINVAL;
+                       info->status = -EINVAL;
                        goto next;
                }
 
-               info.status = -EXDEV;
+               info->status = -EXDEV;
                if (file->f_path.mnt != dst_file->f_path.mnt)
                        goto next;
 
@@ -2781,32 +2798,29 @@ static long btrfs_ioctl_file_extent_same(struct file *file,
                        goto next;
 
                if (S_ISDIR(dst->i_mode)) {
-                       info.status = -EISDIR;
+                       info->status = -EISDIR;
                        goto next;
                }
 
                if (!S_ISREG(dst->i_mode)) {
-                       info.status = -EACCES;
+                       info->status = -EACCES;
                        goto next;
                }
 
-               info.status = btrfs_extent_same(src, off, len, dst,
-                                               info.logical_offset);
-               if (info.status == 0)
-                       info.bytes_deduped += len;
+               info->status = btrfs_extent_same(src, off, len, dst,
+                                               info->logical_offset);
+               if (info->status == 0)
+                       info->bytes_deduped += len;
 
 next:
                if (dst_file)
                        fput(dst_file);
-
-               if (__put_user_unaligned(info.status, &args->info[i].status) ||
-                   __put_user_unaligned(info.bytes_deduped,
-                                        &args->info[i].bytes_deduped)) {
-                       ret = -EFAULT;
-                       goto out;
-               }                                                               
        }
 
+       ret = copy_to_user(argp, same, size);
+       if (ret)
+               ret = -EFAULT;
+
 out:
        mnt_drop_write_file(file);
        return ret;
@@ -3310,7 +3324,7 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
        }
 
        if (!objectid)
-               objectid = root->root_key.objectid;
+               objectid = BTRFS_FS_TREE_OBJECTID;
 
        location.objectid = objectid;
        location.type = BTRFS_ROOT_ITEM_KEY;
index 966b413a33b800d096eda96d662bb3a66770145f..c702cb62f78a310c8d430fe0d98cfb1173479a0f 100644 (file)
@@ -563,11 +563,10 @@ static void btrfs_run_ordered_extent_work(struct btrfs_work *work)
  * wait for all the ordered extents in a root.  This is done when balancing
  * space between drives.
  */
-void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput)
+void btrfs_wait_ordered_extents(struct btrfs_root *root)
 {
        struct list_head splice, works;
        struct btrfs_ordered_extent *ordered, *next;
-       struct inode *inode;
 
        INIT_LIST_HEAD(&splice);
        INIT_LIST_HEAD(&works);
@@ -580,15 +579,6 @@ void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput)
                                           root_extent_list);
                list_move_tail(&ordered->root_extent_list,
                               &root->ordered_extents);
-               /*
-                * the inode may be getting freed (in sys_unlink path).
-                */
-               inode = igrab(ordered->inode);
-               if (!inode) {
-                       cond_resched_lock(&root->ordered_extent_lock);
-                       continue;
-               }
-
                atomic_inc(&ordered->refs);
                spin_unlock(&root->ordered_extent_lock);
 
@@ -605,21 +595,13 @@ void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput)
        list_for_each_entry_safe(ordered, next, &works, work_list) {
                list_del_init(&ordered->work_list);
                wait_for_completion(&ordered->completion);
-
-               inode = ordered->inode;
                btrfs_put_ordered_extent(ordered);
-               if (delay_iput)
-                       btrfs_add_delayed_iput(inode);
-               else
-                       iput(inode);
-
                cond_resched();
        }
        mutex_unlock(&root->fs_info->ordered_operations_mutex);
 }
 
-void btrfs_wait_all_ordered_extents(struct btrfs_fs_info *fs_info,
-                                   int delay_iput)
+void btrfs_wait_all_ordered_extents(struct btrfs_fs_info *fs_info)
 {
        struct btrfs_root *root;
        struct list_head splice;
@@ -637,7 +619,7 @@ void btrfs_wait_all_ordered_extents(struct btrfs_fs_info *fs_info,
                               &fs_info->ordered_roots);
                spin_unlock(&fs_info->ordered_root_lock);
 
-               btrfs_wait_ordered_extents(root, delay_iput);
+               btrfs_wait_ordered_extents(root);
                btrfs_put_fs_root(root);
 
                spin_lock(&fs_info->ordered_root_lock);
index d9a5aa097b4fea86cabf16e649e11775555de260..0c0b35612d7ad1fc5f5c7db5d267e70f319d8529 100644 (file)
@@ -195,9 +195,8 @@ int btrfs_run_ordered_operations(struct btrfs_trans_handle *trans,
 void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans,
                                 struct btrfs_root *root,
                                 struct inode *inode);
-void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput);
-void btrfs_wait_all_ordered_extents(struct btrfs_fs_info *fs_info,
-                                   int delay_iput);
+void btrfs_wait_ordered_extents(struct btrfs_root *root);
+void btrfs_wait_all_ordered_extents(struct btrfs_fs_info *fs_info);
 void btrfs_get_logged_extents(struct btrfs_root *log, struct inode *inode);
 void btrfs_wait_logged_extents(struct btrfs_root *log, u64 transid);
 void btrfs_free_logged_extents(struct btrfs_root *log, u64 transid);
index aacc2121e87c5df2f7dac46e90daca2514a7912f..a5a26320503fd4a82358adff8e614240373ea130 100644 (file)
@@ -1548,7 +1548,7 @@ static int get_new_location(struct inode *reloc_inode, u64 *new_bytenr,
               btrfs_file_extent_other_encoding(leaf, fi));
 
        if (num_bytes != btrfs_file_extent_disk_num_bytes(leaf, fi)) {
-               ret = 1;
+               ret = -EINVAL;
                goto out;
        }
 
@@ -1579,7 +1579,7 @@ int replace_file_extents(struct btrfs_trans_handle *trans,
        u64 end;
        u32 nritems;
        u32 i;
-       int ret;
+       int ret = 0;
        int first = 1;
        int dirty = 0;
 
@@ -1642,11 +1642,13 @@ int replace_file_extents(struct btrfs_trans_handle *trans,
 
                ret = get_new_location(rc->data_inode, &new_bytenr,
                                       bytenr, num_bytes);
-               if (ret > 0) {
-                       WARN_ON(1);
-                       continue;
+               if (ret) {
+                       /*
+                        * Don't have to abort since we've not changed anything
+                        * in the file extent yet.
+                        */
+                       break;
                }
-               BUG_ON(ret < 0);
 
                btrfs_set_file_extent_disk_bytenr(leaf, fi, new_bytenr);
                dirty = 1;
@@ -1656,18 +1658,24 @@ int replace_file_extents(struct btrfs_trans_handle *trans,
                                           num_bytes, parent,
                                           btrfs_header_owner(leaf),
                                           key.objectid, key.offset, 1);
-               BUG_ON(ret);
+               if (ret) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       break;
+               }
 
                ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
                                        parent, btrfs_header_owner(leaf),
                                        key.objectid, key.offset, 1);
-               BUG_ON(ret);
+               if (ret) {
+                       btrfs_abort_transaction(trans, root, ret);
+                       break;
+               }
        }
        if (dirty)
                btrfs_mark_buffer_dirty(leaf);
        if (inode)
                btrfs_add_delayed_iput(inode);
-       return 0;
+       return ret;
 }
 
 static noinline_for_stack
@@ -4238,7 +4246,7 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start)
                err = ret;
                goto out;
        }
-       btrfs_wait_all_ordered_extents(fs_info, 0);
+       btrfs_wait_all_ordered_extents(fs_info);
 
        while (1) {
                mutex_lock(&fs_info->cleaner_mutex);
@@ -4499,19 +4507,19 @@ out:
        return ret;
 }
 
-void btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
-                          struct btrfs_root *root, struct extent_buffer *buf,
-                          struct extent_buffer *cow)
+int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
+                         struct btrfs_root *root, struct extent_buffer *buf,
+                         struct extent_buffer *cow)
 {
        struct reloc_control *rc;
        struct backref_node *node;
        int first_cow = 0;
        int level;
-       int ret;
+       int ret = 0;
 
        rc = root->fs_info->reloc_ctl;
        if (!rc)
-               return;
+               return 0;
 
        BUG_ON(rc->stage == UPDATE_DATA_PTRS &&
               root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID);
@@ -4547,10 +4555,9 @@ void btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
                        rc->nodes_relocated += buf->len;
        }
 
-       if (level == 0 && first_cow && rc->stage == UPDATE_DATA_PTRS) {
+       if (level == 0 && first_cow && rc->stage == UPDATE_DATA_PTRS)
                ret = replace_file_extents(trans, rc, root, cow);
-               BUG_ON(ret);
-       }
+       return ret;
 }
 
 /*
index 0afcd452fcb3d62c9804089ef1cb056687917784..a18e0e23f6a6742cd21277702ed6599df84c32c3 100644 (file)
@@ -158,12 +158,20 @@ struct scrub_fixup_nodatasum {
        int                     mirror_num;
 };
 
+struct scrub_nocow_inode {
+       u64                     inum;
+       u64                     offset;
+       u64                     root;
+       struct list_head        list;
+};
+
 struct scrub_copy_nocow_ctx {
        struct scrub_ctx        *sctx;
        u64                     logical;
        u64                     len;
        int                     mirror_num;
        u64                     physical_for_dev_replace;
+       struct list_head        inodes;
        struct btrfs_work       work;
 };
 
@@ -245,7 +253,7 @@ static void scrub_wr_bio_end_io_worker(struct btrfs_work *work);
 static int write_page_nocow(struct scrub_ctx *sctx,
                            u64 physical_for_dev_replace, struct page *page);
 static int copy_nocow_pages_for_inode(u64 inum, u64 offset, u64 root,
-                                     void *ctx);
+                                     struct scrub_copy_nocow_ctx *ctx);
 static int copy_nocow_pages(struct scrub_ctx *sctx, u64 logical, u64 len,
                            int mirror_num, u64 physical_for_dev_replace);
 static void copy_nocow_pages_worker(struct btrfs_work *work);
@@ -3126,12 +3134,30 @@ static int copy_nocow_pages(struct scrub_ctx *sctx, u64 logical, u64 len,
        nocow_ctx->mirror_num = mirror_num;
        nocow_ctx->physical_for_dev_replace = physical_for_dev_replace;
        nocow_ctx->work.func = copy_nocow_pages_worker;
+       INIT_LIST_HEAD(&nocow_ctx->inodes);
        btrfs_queue_worker(&fs_info->scrub_nocow_workers,
                           &nocow_ctx->work);
 
        return 0;
 }
 
+static int record_inode_for_nocow(u64 inum, u64 offset, u64 root, void *ctx)
+{
+       struct scrub_copy_nocow_ctx *nocow_ctx = ctx;
+       struct scrub_nocow_inode *nocow_inode;
+
+       nocow_inode = kzalloc(sizeof(*nocow_inode), GFP_NOFS);
+       if (!nocow_inode)
+               return -ENOMEM;
+       nocow_inode->inum = inum;
+       nocow_inode->offset = offset;
+       nocow_inode->root = root;
+       list_add_tail(&nocow_inode->list, &nocow_ctx->inodes);
+       return 0;
+}
+
+#define COPY_COMPLETE 1
+
 static void copy_nocow_pages_worker(struct btrfs_work *work)
 {
        struct scrub_copy_nocow_ctx *nocow_ctx =
@@ -3167,8 +3193,7 @@ static void copy_nocow_pages_worker(struct btrfs_work *work)
        }
 
        ret = iterate_inodes_from_logical(logical, fs_info, path,
-                                         copy_nocow_pages_for_inode,
-                                         nocow_ctx);
+                                         record_inode_for_nocow, nocow_ctx);
        if (ret != 0 && ret != -ENOENT) {
                pr_warn("iterate_inodes_from_logical() failed: log %llu, phys %llu, len %llu, mir %u, ret %d\n",
                        logical, physical_for_dev_replace, len, mirror_num,
@@ -3177,7 +3202,33 @@ static void copy_nocow_pages_worker(struct btrfs_work *work)
                goto out;
        }
 
+       btrfs_end_transaction(trans, root);
+       trans = NULL;
+       while (!list_empty(&nocow_ctx->inodes)) {
+               struct scrub_nocow_inode *entry;
+               entry = list_first_entry(&nocow_ctx->inodes,
+                                        struct scrub_nocow_inode,
+                                        list);
+               list_del_init(&entry->list);
+               ret = copy_nocow_pages_for_inode(entry->inum, entry->offset,
+                                                entry->root, nocow_ctx);
+               kfree(entry);
+               if (ret == COPY_COMPLETE) {
+                       ret = 0;
+                       break;
+               } else if (ret) {
+                       break;
+               }
+       }
 out:
+       while (!list_empty(&nocow_ctx->inodes)) {
+               struct scrub_nocow_inode *entry;
+               entry = list_first_entry(&nocow_ctx->inodes,
+                                        struct scrub_nocow_inode,
+                                        list);
+               list_del_init(&entry->list);
+               kfree(entry);
+       }
        if (trans && !IS_ERR(trans))
                btrfs_end_transaction(trans, root);
        if (not_written)
@@ -3190,20 +3241,25 @@ out:
        scrub_pending_trans_workers_dec(sctx);
 }
 
-static int copy_nocow_pages_for_inode(u64 inum, u64 offset, u64 root, void *ctx)
+static int copy_nocow_pages_for_inode(u64 inum, u64 offset, u64 root,
+                                     struct scrub_copy_nocow_ctx *nocow_ctx)
 {
-       struct scrub_copy_nocow_ctx *nocow_ctx = ctx;
        struct btrfs_fs_info *fs_info = nocow_ctx->sctx->dev_root->fs_info;
        struct btrfs_key key;
        struct inode *inode;
        struct page *page;
        struct btrfs_root *local_root;
+       struct btrfs_ordered_extent *ordered;
+       struct extent_map *em;
+       struct extent_state *cached_state = NULL;
+       struct extent_io_tree *io_tree;
        u64 physical_for_dev_replace;
-       u64 len;
+       u64 len = nocow_ctx->len;
+       u64 lockstart = offset, lockend = offset + len - 1;
        unsigned long index;
        int srcu_index;
-       int ret;
-       int err;
+       int ret = 0;
+       int err = 0;
 
        key.objectid = root;
        key.type = BTRFS_ROOT_ITEM_KEY;
@@ -3229,9 +3285,33 @@ static int copy_nocow_pages_for_inode(u64 inum, u64 offset, u64 root, void *ctx)
        mutex_lock(&inode->i_mutex);
        inode_dio_wait(inode);
 
-       ret = 0;
        physical_for_dev_replace = nocow_ctx->physical_for_dev_replace;
-       len = nocow_ctx->len;
+       io_tree = &BTRFS_I(inode)->io_tree;
+
+       lock_extent_bits(io_tree, lockstart, lockend, 0, &cached_state);
+       ordered = btrfs_lookup_ordered_range(inode, lockstart, len);
+       if (ordered) {
+               btrfs_put_ordered_extent(ordered);
+               goto out_unlock;
+       }
+
+       em = btrfs_get_extent(inode, NULL, 0, lockstart, len, 0);
+       if (IS_ERR(em)) {
+               ret = PTR_ERR(em);
+               goto out_unlock;
+       }
+
+       /*
+        * This extent does not actually cover the logical extent anymore,
+        * move on to the next inode.
+        */
+       if (em->block_start > nocow_ctx->logical ||
+           em->block_start + em->block_len < nocow_ctx->logical + len) {
+               free_extent_map(em);
+               goto out_unlock;
+       }
+       free_extent_map(em);
+
        while (len >= PAGE_CACHE_SIZE) {
                index = offset >> PAGE_CACHE_SHIFT;
 again:
@@ -3247,10 +3327,9 @@ again:
                                goto next_page;
                } else {
                        ClearPageError(page);
-                       err = extent_read_full_page(&BTRFS_I(inode)->
-                                                        io_tree,
-                                                       page, btrfs_get_extent,
-                                                       nocow_ctx->mirror_num);
+                       err = extent_read_full_page_nolock(io_tree, page,
+                                                          btrfs_get_extent,
+                                                          nocow_ctx->mirror_num);
                        if (err) {
                                ret = err;
                                goto next_page;
@@ -3264,6 +3343,7 @@ again:
                         * page in the page cache.
                         */
                        if (page->mapping != inode->i_mapping) {
+                               unlock_page(page);
                                page_cache_release(page);
                                goto again;
                        }
@@ -3287,6 +3367,10 @@ next_page:
                physical_for_dev_replace += PAGE_CACHE_SIZE;
                len -= PAGE_CACHE_SIZE;
        }
+       ret = COPY_COMPLETE;
+out_unlock:
+       unlock_extent_cached(io_tree, lockstart, lockend, &cached_state,
+                            GFP_NOFS);
 out:
        mutex_unlock(&inode->i_mutex);
        iput(inode);
index 3aab10ce63e84812b8e9c5a9250235db9b1bbe86..e913328d0f2adc9c3beb2c37556a479c7615d2fa 100644 (file)
@@ -921,7 +921,7 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
                return 0;
        }
 
-       btrfs_wait_all_ordered_extents(fs_info, 1);
+       btrfs_wait_all_ordered_extents(fs_info);
 
        trans = btrfs_attach_transaction_barrier(root);
        if (IS_ERR(trans)) {
@@ -1340,6 +1340,12 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                if (ret)
                        goto restore;
        } else {
+               if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state)) {
+                       btrfs_err(fs_info,
+                               "Remounting read-write after error is not allowed\n");
+                       ret = -EINVAL;
+                       goto restore;
+               }
                if (fs_info->fs_devices->rw_devices == 0) {
                        ret = -EACCES;
                        goto restore;
@@ -1377,6 +1383,16 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                        pr_warn("btrfs: failed to resume dev_replace\n");
                        goto restore;
                }
+
+               if (!fs_info->uuid_root) {
+                       pr_info("btrfs: creating UUID tree\n");
+                       ret = btrfs_create_uuid_tree(fs_info);
+                       if (ret) {
+                               pr_warn("btrfs: failed to create the uuid tree"
+                                       "%d\n", ret);
+                               goto restore;
+                       }
+               }
                sb->s_flags &= ~MS_RDONLY;
        }
 out:
@@ -1762,6 +1778,9 @@ static void btrfs_print_info(void)
 #ifdef CONFIG_BTRFS_DEBUG
                        ", debug=on"
 #endif
+#ifdef CONFIG_BTRFS_ASSERT
+                       ", assert=on"
+#endif
 #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
                        ", integrity-checker=on"
 #endif
index cac4a3f763230f7e448ca6de68a0859a42b13af8..8c81bdc1ef9bae82c92e5a8836a0f911c1547a55 100644 (file)
@@ -1603,7 +1603,7 @@ static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info)
 static inline void btrfs_wait_delalloc_flush(struct btrfs_fs_info *fs_info)
 {
        if (btrfs_test_opt(fs_info->tree_root, FLUSHONCOMMIT))
-               btrfs_wait_all_ordered_extents(fs_info, 1);
+               btrfs_wait_all_ordered_extents(fs_info);
 }
 
 int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
@@ -1838,11 +1838,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
        assert_qgroups_uptodate(trans);
        update_super_roots(root);
 
-       if (!root->fs_info->log_root_recovering) {
-               btrfs_set_super_log_root(root->fs_info->super_copy, 0);
-               btrfs_set_super_log_root_level(root->fs_info->super_copy, 0);
-       }
-
+       btrfs_set_super_log_root(root->fs_info->super_copy, 0);
+       btrfs_set_super_log_root_level(root->fs_info->super_copy, 0);
        memcpy(root->fs_info->super_for_commit, root->fs_info->super_copy,
               sizeof(*root->fs_info->super_copy));
 
index 0d9613c3f5e507cc6087decdbc3ef43e3436b396..79f057c0619a5cfe29a6e47dcd3ebeccebce9809 100644 (file)
@@ -93,7 +93,8 @@
  */
 #define LOG_WALK_PIN_ONLY 0
 #define LOG_WALK_REPLAY_INODES 1
-#define LOG_WALK_REPLAY_ALL 2
+#define LOG_WALK_REPLAY_DIR_INDEX 2
+#define LOG_WALK_REPLAY_ALL 3
 
 static int btrfs_log_inode(struct btrfs_trans_handle *trans,
                             struct btrfs_root *root, struct inode *inode,
@@ -393,6 +394,7 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
                if (inode_item) {
                        struct btrfs_inode_item *item;
                        u64 nbytes;
+                       u32 mode;
 
                        item = btrfs_item_ptr(path->nodes[0], path->slots[0],
                                              struct btrfs_inode_item);
@@ -400,9 +402,19 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
                        item = btrfs_item_ptr(eb, slot,
                                              struct btrfs_inode_item);
                        btrfs_set_inode_nbytes(eb, item, nbytes);
+
+                       /*
+                        * If this is a directory we need to reset the i_size to
+                        * 0 so that we can set it up properly when replaying
+                        * the rest of the items in this log.
+                        */
+                       mode = btrfs_inode_mode(eb, item);
+                       if (S_ISDIR(mode))
+                               btrfs_set_inode_size(eb, item, 0);
                }
        } else if (inode_item) {
                struct btrfs_inode_item *item;
+               u32 mode;
 
                /*
                 * New inode, set nbytes to 0 so that the nbytes comes out
@@ -410,6 +422,15 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans,
                 */
                item = btrfs_item_ptr(eb, slot, struct btrfs_inode_item);
                btrfs_set_inode_nbytes(eb, item, 0);
+
+               /*
+                * If this is a directory we need to reset the i_size to 0 so
+                * that we can set it up properly when replaying the rest of
+                * the items in this log.
+                */
+               mode = btrfs_inode_mode(eb, item);
+               if (S_ISDIR(mode))
+                       btrfs_set_inode_size(eb, item, 0);
        }
 insert:
        btrfs_release_path(path);
@@ -1496,6 +1517,7 @@ static noinline int insert_one_name(struct btrfs_trans_handle *trans,
                iput(inode);
                return -EIO;
        }
+
        ret = btrfs_add_link(trans, dir, inode, name, name_len, 1, index);
 
        /* FIXME, put inode into FIXUP list */
@@ -1534,6 +1556,7 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,
        u8 log_type;
        int exists;
        int ret = 0;
+       bool update_size = (key->type == BTRFS_DIR_INDEX_KEY);
 
        dir = read_one_inode(root, key->objectid);
        if (!dir)
@@ -1604,6 +1627,10 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans,
                goto insert;
 out:
        btrfs_release_path(path);
+       if (!ret && update_size) {
+               btrfs_i_size_write(dir, dir->i_size + name_len * 2);
+               ret = btrfs_update_inode(trans, root, dir);
+       }
        kfree(name);
        iput(dir);
        return ret;
@@ -1614,6 +1641,7 @@ insert:
                              name, name_len, log_type, &log_key);
        if (ret && ret != -ENOENT)
                goto out;
+       update_size = false;
        ret = 0;
        goto out;
 }
@@ -2027,6 +2055,15 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
                        if (ret)
                                break;
                }
+
+               if (key.type == BTRFS_DIR_INDEX_KEY &&
+                   wc->stage == LOG_WALK_REPLAY_DIR_INDEX) {
+                       ret = replay_one_dir_item(wc->trans, root, path,
+                                                 eb, i, &key);
+                       if (ret)
+                               break;
+               }
+
                if (wc->stage < LOG_WALK_REPLAY_ALL)
                        continue;
 
@@ -2048,8 +2085,7 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
                                                eb, i, &key);
                        if (ret)
                                break;
-               } else if (key.type == BTRFS_DIR_ITEM_KEY ||
-                          key.type == BTRFS_DIR_INDEX_KEY) {
+               } else if (key.type == BTRFS_DIR_ITEM_KEY) {
                        ret = replay_one_dir_item(wc->trans, root, path,
                                                  eb, i, &key);
                        if (ret)
@@ -3805,6 +3841,7 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans,
        int ret = 0;
        struct btrfs_root *root;
        struct dentry *old_parent = NULL;
+       struct inode *orig_inode = inode;
 
        /*
         * for regular files, if its inode is already on disk, we don't
@@ -3824,7 +3861,14 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans,
        }
 
        while (1) {
-               BTRFS_I(inode)->logged_trans = trans->transid;
+               /*
+                * If we are logging a directory then we start with our inode,
+                * not our parents inode, so we need to skipp setting the
+                * logged_trans so that further down in the log code we don't
+                * think this inode has already been logged.
+                */
+               if (inode != orig_inode)
+                       BTRFS_I(inode)->logged_trans = trans->transid;
                smp_mb();
 
                if (BTRFS_I(inode)->last_unlink_trans > last_committed) {
index 0052ca8264d9b37cc171e52e0954b165fd6dad46..043b215769c2c68c538ea147d5cde0721221b833 100644 (file)
@@ -796,7 +796,8 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
                        fs_devices->rotating = 1;
 
                fs_devices->open_devices++;
-               if (device->writeable && !device->is_tgtdev_for_dev_replace) {
+               if (device->writeable &&
+                   device->devid != BTRFS_DEV_REPLACE_DEVID) {
                        fs_devices->rw_devices++;
                        list_add(&device->dev_alloc_list,
                                 &fs_devices->alloc_list);
@@ -911,9 +912,9 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
        if (disk_super->label[0]) {
                if (disk_super->label[BTRFS_LABEL_SIZE - 1])
                        disk_super->label[BTRFS_LABEL_SIZE - 1] = '\0';
-               printk(KERN_INFO "device label %s ", disk_super->label);
+               printk(KERN_INFO "btrfs: device label %s ", disk_super->label);
        } else {
-               printk(KERN_INFO "device fsid %pU ", disk_super->fsid);
+               printk(KERN_INFO "btrfs: device fsid %pU ", disk_super->fsid);
        }
 
        printk(KERN_CONT "devid %llu transid %llu %s\n", devid, transid, path);
@@ -1715,6 +1716,7 @@ void btrfs_rm_dev_replace_srcdev(struct btrfs_fs_info *fs_info,
                                 struct btrfs_device *srcdev)
 {
        WARN_ON(!mutex_is_locked(&fs_info->fs_devices->device_list_mutex));
+
        list_del_rcu(&srcdev->dev_list);
        list_del_rcu(&srcdev->dev_alloc_list);
        fs_info->fs_devices->num_devices--;
@@ -1724,9 +1726,13 @@ void btrfs_rm_dev_replace_srcdev(struct btrfs_fs_info *fs_info,
        }
        if (srcdev->can_discard)
                fs_info->fs_devices->num_can_discard--;
-       if (srcdev->bdev)
+       if (srcdev->bdev) {
                fs_info->fs_devices->open_devices--;
 
+               /* zero out the old super */
+               btrfs_scratch_superblock(srcdev);
+       }
+
        call_rcu(&srcdev->rcu, free_device);
 }
 
index 25badd1aec5c677215f20d9bd970261deab2dd35..f4a08d7fa2f70a58a8513110988cc4928a674bdb 100644 (file)
@@ -56,7 +56,7 @@ void __cachefiles_printk_object(struct cachefiles_object *object,
                       object->fscache.cookie->parent,
                       object->fscache.cookie->netfs_data,
                       object->fscache.cookie->flags);
-               if (keybuf)
+               if (keybuf && cookie->def)
                        keylen = cookie->def->get_key(cookie->netfs_data, keybuf,
                                                      CACHEFILES_KEYBUF_SIZE);
                else
index 34c88b83e39f1214b0ed7f2c22bc58f5acd00fa4..12b0eef84183be5edb35627b169cbe49a516a961 100644 (file)
@@ -162,8 +162,9 @@ int cachefiles_update_object_xattr(struct cachefiles_object *object,
 int cachefiles_check_auxdata(struct cachefiles_object *object)
 {
        struct cachefiles_xattr *auxbuf;
+       enum fscache_checkaux validity;
        struct dentry *dentry = object->dentry;
-       unsigned int dlen;
+       ssize_t xlen;
        int ret;
 
        ASSERT(dentry);
@@ -174,22 +175,22 @@ int cachefiles_check_auxdata(struct cachefiles_object *object)
        if (!auxbuf)
                return -ENOMEM;
 
-       auxbuf->len = vfs_getxattr(dentry, cachefiles_xattr_cache,
-                                  &auxbuf->type, 512 + 1);
-       if (auxbuf->len < 1)
-               return -ESTALE;
-
-       if (auxbuf->type != object->fscache.cookie->def->type)
-               return -ESTALE;
+       xlen = vfs_getxattr(dentry, cachefiles_xattr_cache,
+                           &auxbuf->type, 512 + 1);
+       ret = -ESTALE;
+       if (xlen < 1 ||
+           auxbuf->type != object->fscache.cookie->def->type)
+               goto error;
 
-       dlen = auxbuf->len - 1;
-       ret = fscache_check_aux(&object->fscache, &auxbuf->data, dlen);
+       xlen--;
+       validity = fscache_check_aux(&object->fscache, &auxbuf->data, xlen);
+       if (validity != FSCACHE_CHECKAUX_OKAY)
+               goto error;
 
+       ret = 0;
+error:
        kfree(auxbuf);
-       if (ret != FSCACHE_CHECKAUX_OKAY)
-               return -ESTALE;
-
-       return 0;
+       return ret;
 }
 
 /*
index ea723a5e8226231d64cd85eab065c7f91801a3a0..6d0b07217ac9a6ec5b2887125fdb3fa60800642c 100644 (file)
@@ -132,5 +132,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
 extern const struct export_operations cifs_export_ops;
 #endif /* CONFIG_CIFS_NFSD_EXPORT */
 
-#define CIFS_VERSION   "2.01"
+#define CIFS_VERSION   "2.02"
 #endif                         /* _CIFSFS_H */
index cfa14c80ef3b6a76f5a1cfe1de5c8a6878d988e3..52b6f6c26bfcbe37d2994ba0fe3fa0b3779016d4 100644 (file)
@@ -547,9 +547,6 @@ struct TCP_Server_Info {
        unsigned int max_rw;    /* maxRw specifies the maximum */
        /* message size the server can send or receive for */
        /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
-       unsigned int max_vcs;   /* maximum number of smb sessions, at least
-                                  those that can be specified uniquely with
-                                  vcnumbers */
        unsigned int capabilities; /* selective disabling of caps by smb sess */
        int timeAdj;  /* Adjust for difference in server time zone in sec */
        __u64 CurrentMid;         /* multiplex id - rotating counter */
@@ -715,7 +712,6 @@ struct cifs_ses {
        enum statusEnum status;
        unsigned overrideSecFlg;  /* if non-zero override global sec flags */
        __u16 ipc_tid;          /* special tid for connection to IPC share */
-       __u16 vcnum;
        char *serverOS;         /* name of operating system underlying server */
        char *serverNOS;        /* name of network operating system of server */
        char *serverDomain;     /* security realm of server */
@@ -1272,6 +1268,7 @@ struct dfs_info3_param {
 #define CIFS_FATTR_DELETE_PENDING      0x2
 #define CIFS_FATTR_NEED_REVAL          0x4
 #define CIFS_FATTR_INO_COLLISION       0x8
+#define CIFS_FATTR_UNKNOWN_NLINK       0x10
 
 struct cifs_fattr {
        u32             cf_flags;
index 948676db8e2ea5f65d276535caa087c86792b18c..a630475e421c421ef38f6633ddb31c8351827752 100644 (file)
@@ -2652,26 +2652,7 @@ typedef struct file_xattr_info {
 } __attribute__((packed)) FILE_XATTR_INFO; /* extended attribute info
                                              level 0x205 */
 
-
-/* flags for chattr command */
-#define EXT_SECURE_DELETE              0x00000001 /* EXT3_SECRM_FL */
-#define EXT_ENABLE_UNDELETE            0x00000002 /* EXT3_UNRM_FL */
-/* Reserved for compress file 0x4 */
-#define EXT_SYNCHRONOUS                        0x00000008 /* EXT3_SYNC_FL */
-#define EXT_IMMUTABLE_FL               0x00000010 /* EXT3_IMMUTABLE_FL */
-#define EXT_OPEN_APPEND_ONLY           0x00000020 /* EXT3_APPEND_FL */
-#define EXT_DO_NOT_BACKUP              0x00000040 /* EXT3_NODUMP_FL */
-#define EXT_NO_UPDATE_ATIME            0x00000080 /* EXT3_NOATIME_FL */
-/* 0x100 through 0x800 reserved for compression flags and are GET-ONLY */
-#define EXT_HASH_TREE_INDEXED_DIR      0x00001000 /* GET-ONLY EXT3_INDEX_FL */
-/* 0x2000 reserved for IMAGIC_FL */
-#define EXT_JOURNAL_THIS_FILE  0x00004000 /* GET-ONLY EXT3_JOURNAL_DATA_FL */
-/* 0x8000 reserved for EXT3_NOTAIL_FL */
-#define EXT_SYNCHRONOUS_DIR            0x00010000 /* EXT3_DIRSYNC_FL */
-#define EXT_TOPDIR                     0x00020000 /* EXT3_TOPDIR_FL */
-
-#define EXT_SET_MASK                   0x000300FF
-#define EXT_GET_MASK                   0x0003DFFF
+/* flags for lsattr and chflags commands removed arein uapi/linux/fs.h */
 
 typedef struct file_chattr_info {
        __le64  mask; /* list of all possible attribute bits */
index a3d74fea16233ef9d4c32a0179b4b96cccb8fa2b..4baf35949b51a16a395a698f40b66dd312a14246 100644 (file)
@@ -463,7 +463,6 @@ decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
                               cifs_max_pending);
        set_credits(server, server->maxReq);
        server->maxBuf = le16_to_cpu(rsp->MaxBufSize);
-       server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
        /* even though we do not use raw we might as well set this
        accurately, in case we ever find a need for it */
        if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
index d3e2eaa503a631e90d918d8ae1d3c9cc2bb66cda..5384c2a640ca6fc06962a01261ca4f8ce890b246 100644 (file)
@@ -500,6 +500,7 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
                if (server->ops->close)
                        server->ops->close(xid, tcon, &fid);
                cifs_del_pending_open(&open);
+               fput(file);
                rc = -ENOMEM;
        }
 
index eb955b525e55307a18c1b534e95e5bfbe8462764..7ddddf2e25046af5fceb6fcbe097e2b14750710c 100644 (file)
@@ -3254,6 +3254,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
        /*
         * Reads as many pages as possible from fscache. Returns -ENOBUFS
         * immediately if the cookie is negative
+        *
+        * After this point, every page in the list might have PG_fscache set,
+        * so we will need to clean that up off of every page we don't use.
         */
        rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list,
                                         &num_pages);
@@ -3376,6 +3379,11 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
                kref_put(&rdata->refcount, cifs_readdata_release);
        }
 
+       /* Any pages that have been shown to fscache but didn't get added to
+        * the pagecache must be uncached before they get returned to the
+        * allocator.
+        */
+       cifs_fscache_readpages_cancel(mapping->host, page_list);
        return rc;
 }
 
index 2f4bc5a58054e65475b675c4e591a72bbfb706b0..b3258f35e88a5126d61b463bb4d96387e5dcba42 100644 (file)
@@ -223,6 +223,13 @@ void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
                fscache_uncache_page(CIFS_I(inode)->fscache, page);
 }
 
+void __cifs_fscache_readpages_cancel(struct inode *inode, struct list_head *pages)
+{
+       cifs_dbg(FYI, "%s: (fsc: %p, i: %p)\n",
+                __func__, CIFS_I(inode)->fscache, inode);
+       fscache_readpages_cancel(CIFS_I(inode)->fscache, pages);
+}
+
 void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
 {
        struct cifsInodeInfo *cifsi = CIFS_I(inode);
index 63539323e0b960f3ecf9788eca6e67ba0ec8ce67..24794b6cd8ec5d18ce9248a6469315a1d8eebf08 100644 (file)
@@ -54,6 +54,7 @@ extern int __cifs_readpages_from_fscache(struct inode *,
                                         struct address_space *,
                                         struct list_head *,
                                         unsigned *);
+extern void __cifs_fscache_readpages_cancel(struct inode *, struct list_head *);
 
 extern void __cifs_readpage_to_fscache(struct inode *, struct page *);
 
@@ -91,6 +92,13 @@ static inline void cifs_readpage_to_fscache(struct inode *inode,
                __cifs_readpage_to_fscache(inode, page);
 }
 
+static inline void cifs_fscache_readpages_cancel(struct inode *inode,
+                                                struct list_head *pages)
+{
+       if (CIFS_I(inode)->fscache)
+               return __cifs_fscache_readpages_cancel(inode, pages);
+}
+
 #else /* CONFIG_CIFS_FSCACHE */
 static inline int cifs_fscache_register(void) { return 0; }
 static inline void cifs_fscache_unregister(void) {}
@@ -131,6 +139,11 @@ static inline int cifs_readpages_from_fscache(struct inode *inode,
 static inline void cifs_readpage_to_fscache(struct inode *inode,
                        struct page *page) {}
 
+static inline void cifs_fscache_readpages_cancel(struct inode *inode,
+                                                struct list_head *pages)
+{
+}
+
 #endif /* CONFIG_CIFS_FSCACHE */
 
 #endif /* _CIFS_FSCACHE_H */
index f9ff9c173f78ad6a8abcc6afb56849109dbfd515..867b7cdc794a221a6eb21257d20bdc3f9e516248 100644 (file)
@@ -120,6 +120,33 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
        cifs_i->invalid_mapping = true;
 }
 
+/*
+ * copy nlink to the inode, unless it wasn't provided.  Provide
+ * sane values if we don't have an existing one and none was provided
+ */
+static void
+cifs_nlink_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
+{
+       /*
+        * if we're in a situation where we can't trust what we
+        * got from the server (readdir, some non-unix cases)
+        * fake reasonable values
+        */
+       if (fattr->cf_flags & CIFS_FATTR_UNKNOWN_NLINK) {
+               /* only provide fake values on a new inode */
+               if (inode->i_state & I_NEW) {
+                       if (fattr->cf_cifsattrs & ATTR_DIRECTORY)
+                               set_nlink(inode, 2);
+                       else
+                               set_nlink(inode, 1);
+               }
+               return;
+       }
+
+       /* we trust the server, so update it */
+       set_nlink(inode, fattr->cf_nlink);
+}
+
 /* populate an inode with info from a cifs_fattr struct */
 void
 cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
@@ -134,7 +161,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
        inode->i_mtime = fattr->cf_mtime;
        inode->i_ctime = fattr->cf_ctime;
        inode->i_rdev = fattr->cf_rdev;
-       set_nlink(inode, fattr->cf_nlink);
+       cifs_nlink_fattr_to_inode(inode, fattr);
        inode->i_uid = fattr->cf_uid;
        inode->i_gid = fattr->cf_gid;
 
@@ -541,6 +568,7 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
        fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
        fattr->cf_createtime = le64_to_cpu(info->CreationTime);
 
+       fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
        if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
                fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
                fattr->cf_dtype = DT_DIR;
@@ -548,7 +576,8 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
                 * Server can return wrong NumberOfLinks value for directories
                 * when Unix extensions are disabled - fake it.
                 */
-               fattr->cf_nlink = 2;
+               if (!tcon->unix_ext)
+                       fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
        } else if (fattr->cf_cifsattrs & ATTR_REPARSE) {
                fattr->cf_mode = S_IFLNK;
                fattr->cf_dtype = DT_LNK;
@@ -561,11 +590,15 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
                if (fattr->cf_cifsattrs & ATTR_READONLY)
                        fattr->cf_mode &= ~(S_IWUGO);
 
-               fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
-               if (fattr->cf_nlink < 1) {
-                       cifs_dbg(1, "replacing bogus file nlink value %u\n",
+               /*
+                * Don't accept zero nlink from non-unix servers unless
+                * delete is pending.  Instead mark it as unknown.
+                */
+               if ((fattr->cf_nlink < 1) && !tcon->unix_ext &&
+                   !info->DeletePending) {
+                       cifs_dbg(1, "bogus file nlink value %u\n",
                                fattr->cf_nlink);
-                       fattr->cf_nlink = 1;
+                       fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
                }
        }
 
index 42ef03be089f2bc9aaabd2e3f40d2b6d6ac207a8..53a75f3d0179231d395611f61f2897c9a52f33de 100644 (file)
@@ -180,6 +180,9 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
                fattr->cf_dtype = DT_REG;
        }
 
+       /* non-unix readdir doesn't provide nlink */
+       fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
+
        if (fattr->cf_cifsattrs & ATTR_READONLY)
                fattr->cf_mode &= ~S_IWUGO;
 
index 5f99b7f19e7870d72aa6f1945550c41ca34e173d..352358de1d7e37a8126d61d76898112393f64d08 100644 (file)
 #include <linux/slab.h>
 #include "cifs_spnego.h"
 
-/*
- * Checks if this is the first smb session to be reconnected after
- * the socket has been reestablished (so we know whether to use vc 0).
- * Called while holding the cifs_tcp_ses_lock, so do not block
- */
-static bool is_first_ses_reconnect(struct cifs_ses *ses)
-{
-       struct list_head *tmp;
-       struct cifs_ses *tmp_ses;
-
-       list_for_each(tmp, &ses->server->smb_ses_list) {
-               tmp_ses = list_entry(tmp, struct cifs_ses,
-                                    smb_ses_list);
-               if (tmp_ses->need_reconnect == false)
-                       return false;
-       }
-       /* could not find a session that was already connected,
-          this must be the first one we are reconnecting */
-       return true;
-}
-
-/*
- *     vc number 0 is treated specially by some servers, and should be the
- *      first one we request.  After that we can use vcnumbers up to maxvcs,
- *     one for each smb session (some Windows versions set maxvcs incorrectly
- *     so maxvc=1 can be ignored).  If we have too many vcs, we can reuse
- *     any vc but zero (some servers reset the connection on vcnum zero)
- *
- */
-static __le16 get_next_vcnum(struct cifs_ses *ses)
-{
-       __u16 vcnum = 0;
-       struct list_head *tmp;
-       struct cifs_ses *tmp_ses;
-       __u16 max_vcs = ses->server->max_vcs;
-       __u16 i;
-       int free_vc_found = 0;
-
-       /* Quoting the MS-SMB specification: "Windows-based SMB servers set this
-       field to one but do not enforce this limit, which allows an SMB client
-       to establish more virtual circuits than allowed by this value ... but
-       other server implementations can enforce this limit." */
-       if (max_vcs < 2)
-               max_vcs = 0xFFFF;
-
-       spin_lock(&cifs_tcp_ses_lock);
-       if ((ses->need_reconnect) && is_first_ses_reconnect(ses))
-                       goto get_vc_num_exit;  /* vcnum will be zero */
-       for (i = ses->server->srv_count - 1; i < max_vcs; i++) {
-               if (i == 0) /* this is the only connection, use vc 0 */
-                       break;
-
-               free_vc_found = 1;
-
-               list_for_each(tmp, &ses->server->smb_ses_list) {
-                       tmp_ses = list_entry(tmp, struct cifs_ses,
-                                            smb_ses_list);
-                       if (tmp_ses->vcnum == i) {
-                               free_vc_found = 0;
-                               break; /* found duplicate, try next vcnum */
-                       }
-               }
-               if (free_vc_found)
-                       break; /* we found a vcnumber that will work - use it */
-       }
-
-       if (i == 0)
-               vcnum = 0; /* for most common case, ie if one smb session, use
-                             vc zero.  Also for case when no free vcnum, zero
-                             is safest to send (some clients only send zero) */
-       else if (free_vc_found == 0)
-               vcnum = 1;  /* we can not reuse vc=0 safely, since some servers
-                               reset all uids on that, but 1 is ok. */
-       else
-               vcnum = i;
-       ses->vcnum = vcnum;
-get_vc_num_exit:
-       spin_unlock(&cifs_tcp_ses_lock);
-
-       return cpu_to_le16(vcnum);
-}
-
 static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB)
 {
        __u32 capabilities = 0;
@@ -128,7 +46,7 @@ static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB)
                                        CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4,
                                        USHRT_MAX));
        pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
-       pSMB->req.VcNumber = get_next_vcnum(ses);
+       pSMB->req.VcNumber = __constant_cpu_to_le16(1);
 
        /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
 
index 318e8433527c432984e61bf68594e305da3a840c..b2a86e324aac05f7bf64b7ce0d0e2c30d91f3d68 100644 (file)
@@ -586,7 +586,8 @@ int __fscache_check_consistency(struct fscache_cookie *cookie)
 
        fscache_operation_init(op, NULL, NULL);
        op->flags = FSCACHE_OP_MYTHREAD |
-               (1 << FSCACHE_OP_WAITING);
+               (1 << FSCACHE_OP_WAITING) |
+               (1 << FSCACHE_OP_UNUSE_COOKIE);
 
        spin_lock(&cookie->lock);
 
index 62b43b577bfce40b116a7a8eb77a91cea1c8b7b4..b7989f2ab4c471f92238fa29d50e7b6d357d8c87 100644 (file)
@@ -182,6 +182,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
        struct inode *inode;
        struct dentry *parent;
        struct fuse_conn *fc;
+       struct fuse_inode *fi;
        int ret;
 
        inode = ACCESS_ONCE(entry->d_inode);
@@ -228,7 +229,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
                if (!err && !outarg.nodeid)
                        err = -ENOENT;
                if (!err) {
-                       struct fuse_inode *fi = get_fuse_inode(inode);
+                       fi = get_fuse_inode(inode);
                        if (outarg.nodeid != get_node_id(inode)) {
                                fuse_queue_forget(fc, forget, outarg.nodeid, 1);
                                goto invalid;
@@ -246,8 +247,11 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
                                       attr_version);
                fuse_change_entry_timeout(entry, &outarg);
        } else if (inode) {
-               fc = get_fuse_conn(inode);
-               if (fc->readdirplus_auto) {
+               fi = get_fuse_inode(inode);
+               if (flags & LOOKUP_RCU) {
+                       if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state))
+                               return -ECHILD;
+               } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) {
                        parent = dget_parent(entry);
                        fuse_advise_use_readdirplus(parent->d_inode);
                        dput(parent);
@@ -259,7 +263,8 @@ out:
 
 invalid:
        ret = 0;
-       if (check_submounts_and_drop(entry) != 0)
+
+       if (!(flags & LOOKUP_RCU) && check_submounts_and_drop(entry) != 0)
                ret = 1;
        goto out;
 }
@@ -1063,6 +1068,8 @@ static int fuse_access(struct inode *inode, int mask)
        struct fuse_access_in inarg;
        int err;
 
+       BUG_ON(mask & MAY_NOT_BLOCK);
+
        if (fc->no_access)
                return 0;
 
@@ -1150,9 +1157,6 @@ static int fuse_permission(struct inode *inode, int mask)
                   noticed immediately, only after the attribute
                   timeout has expired */
        } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
-               if (mask & MAY_NOT_BLOCK)
-                       return -ECHILD;
-
                err = fuse_access(inode, mask);
        } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
                if (!(inode->i_mode & S_IXUGO)) {
@@ -1291,6 +1295,8 @@ static int fuse_direntplus_link(struct file *file,
        }
 
 found:
+       if (fc->readdirplus_auto)
+               set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state);
        fuse_change_entry_timeout(dentry, o);
 
        err = 0;
index d409deafc67b2f6c94fb3fa53b96a21c60585d56..4598345ab87d683dba75022a4a07981dbfb458ed 100644 (file)
@@ -2467,6 +2467,7 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
 {
        struct fuse_file *ff = file->private_data;
        struct inode *inode = file->f_inode;
+       struct fuse_inode *fi = get_fuse_inode(inode);
        struct fuse_conn *fc = ff->fc;
        struct fuse_req *req;
        struct fuse_fallocate_in inarg = {
@@ -2484,10 +2485,20 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
 
        if (lock_inode) {
                mutex_lock(&inode->i_mutex);
-               if (mode & FALLOC_FL_PUNCH_HOLE)
-                       fuse_set_nowrite(inode);
+               if (mode & FALLOC_FL_PUNCH_HOLE) {
+                       loff_t endbyte = offset + length - 1;
+                       err = filemap_write_and_wait_range(inode->i_mapping,
+                                                          offset, endbyte);
+                       if (err)
+                               goto out;
+
+                       fuse_sync_writes(inode);
+               }
        }
 
+       if (!(mode & FALLOC_FL_KEEP_SIZE))
+               set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
+
        req = fuse_get_req_nopages(fc);
        if (IS_ERR(req)) {
                err = PTR_ERR(req);
@@ -2520,11 +2531,11 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
        fuse_invalidate_attr(inode);
 
 out:
-       if (lock_inode) {
-               if (mode & FALLOC_FL_PUNCH_HOLE)
-                       fuse_release_nowrite(inode);
+       if (!(mode & FALLOC_FL_KEEP_SIZE))
+               clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
+
+       if (lock_inode)
                mutex_unlock(&inode->i_mutex);
-       }
 
        return err;
 }
index 5ced199b50bbb19a9dcd8fb42313de4afba26d6c..5b9e6f3b6aef4fc55aaaaaa94666dd532c4fbffc 100644 (file)
@@ -115,6 +115,8 @@ struct fuse_inode {
 enum {
        /** Advise readdirplus  */
        FUSE_I_ADVISE_RDPLUS,
+       /** Initialized with readdirplus */
+       FUSE_I_INIT_RDPLUS,
        /** An operation changing file size is in progress  */
        FUSE_I_SIZE_UNSTABLE,
 };
index 64915eeae5a7112f59256185a00a1cc9f3b2a193..ced3257f06e84bd24b6d96063a4f88f5e2b81525 100644 (file)
@@ -694,8 +694,10 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 
        mark_inode_dirty(inode);
        d_instantiate(dentry, inode);
-       if (file)
+       if (file) {
+               *opened |= FILE_CREATED;
                error = finish_open(file, dentry, gfs2_open_common, opened);
+       }
        gfs2_glock_dq_uninit(ghs);
        gfs2_glock_dq_uninit(ghs + 1);
        return error;
index 0dc4cbf21f377681aa611578a38ab80c0af24646..645268f23eb64cb8c2931ce33391beb2d0080c36 100644 (file)
@@ -2656,6 +2656,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
        int acc_mode;
        int create_error = 0;
        struct dentry *const DENTRY_NOT_SET = (void *) -1UL;
+       bool excl;
 
        BUG_ON(dentry->d_inode);
 
@@ -2669,10 +2670,9 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
        if ((open_flag & O_CREAT) && !IS_POSIXACL(dir))
                mode &= ~current_umask();
 
-       if ((open_flag & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT)) {
+       excl = (open_flag & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT);
+       if (excl)
                open_flag &= ~O_TRUNC;
-               *opened |= FILE_CREATED;
-       }
 
        /*
         * Checking write permission is tricky, bacuse we don't know if we are
@@ -2725,12 +2725,6 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
                goto out;
        }
 
-       acc_mode = op->acc_mode;
-       if (*opened & FILE_CREATED) {
-               fsnotify_create(dir, dentry);
-               acc_mode = MAY_OPEN;
-       }
-
        if (error) {    /* returned 1, that is */
                if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) {
                        error = -EIO;
@@ -2740,9 +2734,19 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
                        dput(dentry);
                        dentry = file->f_path.dentry;
                }
-               if (create_error && dentry->d_inode == NULL) {
-                       error = create_error;
-                       goto out;
+               if (*opened & FILE_CREATED)
+                       fsnotify_create(dir, dentry);
+               if (!dentry->d_inode) {
+                       WARN_ON(*opened & FILE_CREATED);
+                       if (create_error) {
+                               error = create_error;
+                               goto out;
+                       }
+               } else {
+                       if (excl && !(*opened & FILE_CREATED)) {
+                               error = -EEXIST;
+                               goto out;
+                       }
                }
                goto looked_up;
        }
@@ -2751,6 +2755,12 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
         * We didn't have the inode before the open, so check open permission
         * here.
         */
+       acc_mode = op->acc_mode;
+       if (*opened & FILE_CREATED) {
+               WARN_ON(!(open_flag & O_CREAT));
+               fsnotify_create(dir, dentry);
+               acc_mode = MAY_OPEN;
+       }
        error = may_open(&file->f_path, acc_mode, open_flag);
        if (error)
                fput(file);
index de434f309af037c5196335d41666312a69bc50a7..02b0df769e2db23d18d7787e27066ebaa684bbd0 100644 (file)
@@ -1392,6 +1392,9 @@ static int nfs_finish_open(struct nfs_open_context *ctx,
 {
        int err;
 
+       if ((open_flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+               *opened |= FILE_CREATED;
+
        err = finish_open(file, dentry, do_open, opened);
        if (err)
                goto out;
@@ -1455,7 +1458,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
 
        trace_nfs_atomic_open_enter(dir, ctx, open_flags);
        nfs_block_sillyrename(dentry->d_parent);
-       inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr);
+       inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr, opened);
        nfs_unblock_sillyrename(dentry->d_parent);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
index e5b804dd944c16a8adf4de17ee6588562cec55e8..77efaf15ec9019a2a6ed4527b214a166796497c4 100644 (file)
@@ -19,6 +19,7 @@ nfs4_file_open(struct inode *inode, struct file *filp)
        struct inode *dir;
        unsigned openflags = filp->f_flags;
        struct iattr attr;
+       int opened = 0;
        int err;
 
        /*
@@ -55,7 +56,7 @@ nfs4_file_open(struct inode *inode, struct file *filp)
                nfs_wb_all(inode);
        }
 
-       inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr);
+       inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr, &opened);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                switch (err) {
index 95604f64cab86632d7a166ce588ea9ffd5d87e95..c7c295e556ed87501c069053d0c133e44dcadc97 100644 (file)
@@ -185,6 +185,7 @@ nfs4_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds)
        if (status)
                goto out_put;
 
+       smp_wmb();
        ds->ds_clp = clp;
        dprintk("%s [new] addr: %s\n", __func__, ds->ds_remotestr);
 out:
@@ -801,34 +802,35 @@ nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
        struct nfs4_file_layout_dsaddr *dsaddr = FILELAYOUT_LSEG(lseg)->dsaddr;
        struct nfs4_pnfs_ds *ds = dsaddr->ds_list[ds_idx];
        struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg);
-
-       if (filelayout_test_devid_unavailable(devid))
-               return NULL;
+       struct nfs4_pnfs_ds *ret = ds;
 
        if (ds == NULL) {
                printk(KERN_ERR "NFS: %s: No data server for offset index %d\n",
                        __func__, ds_idx);
                filelayout_mark_devid_invalid(devid);
-               return NULL;
+               goto out;
        }
+       smp_rmb();
        if (ds->ds_clp)
-               return ds;
+               goto out_test_devid;
 
        if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) {
                struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode);
                int err;
 
                err = nfs4_ds_connect(s, ds);
-               if (err) {
+               if (err)
                        nfs4_mark_deviceid_unavailable(devid);
-                       ds = NULL;
-               }
                nfs4_clear_ds_conn_bit(ds);
        } else {
                /* Either ds is connected, or ds is NULL */
                nfs4_wait_ds_connect(ds);
        }
-       return ds;
+out_test_devid:
+       if (filelayout_test_devid_unavailable(devid))
+               ret = NULL;
+out:
+       return ret;
 }
 
 module_param(dataserver_retrans, uint, 0644);
index 989bb9d3074d0d4c88d63a486f05491423b090d4..d53d6785cba27f5c6442831e51eded9d04b054f3 100644 (file)
@@ -912,6 +912,7 @@ struct nfs4_opendata {
        struct iattr attrs;
        unsigned long timestamp;
        unsigned int rpc_done : 1;
+       unsigned int file_created : 1;
        unsigned int is_recover : 1;
        int rpc_status;
        int cancelled;
@@ -1946,8 +1947,13 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
 
        nfs_fattr_map_and_free_names(server, &data->f_attr);
 
-       if (o_arg->open_flags & O_CREAT)
+       if (o_arg->open_flags & O_CREAT) {
                update_changeattr(dir, &o_res->cinfo);
+               if (o_arg->open_flags & O_EXCL)
+                       data->file_created = 1;
+               else if (o_res->cinfo.before != o_res->cinfo.after)
+                       data->file_created = 1;
+       }
        if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0)
                server->caps &= ~NFS_CAP_POSIX_LOCK;
        if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
@@ -2191,7 +2197,8 @@ static int _nfs4_do_open(struct inode *dir,
                        struct nfs_open_context *ctx,
                        int flags,
                        struct iattr *sattr,
-                       struct nfs4_label *label)
+                       struct nfs4_label *label,
+                       int *opened)
 {
        struct nfs4_state_owner  *sp;
        struct nfs4_state     *state = NULL;
@@ -2261,6 +2268,8 @@ static int _nfs4_do_open(struct inode *dir,
                        nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel);
                }
        }
+       if (opendata->file_created)
+               *opened |= FILE_CREATED;
 
        if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server))
                *ctx_th = opendata->f_attr.mdsthreshold;
@@ -2289,7 +2298,8 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir,
                                        struct nfs_open_context *ctx,
                                        int flags,
                                        struct iattr *sattr,
-                                       struct nfs4_label *label)
+                                       struct nfs4_label *label,
+                                       int *opened)
 {
        struct nfs_server *server = NFS_SERVER(dir);
        struct nfs4_exception exception = { };
@@ -2297,7 +2307,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir,
        int status;
 
        do {
-               status = _nfs4_do_open(dir, ctx, flags, sattr, label);
+               status = _nfs4_do_open(dir, ctx, flags, sattr, label, opened);
                res = ctx->state;
                trace_nfs4_open_file(ctx, flags, status);
                if (status == 0)
@@ -2659,7 +2669,8 @@ out:
 }
 
 static struct inode *
-nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr)
+nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx,
+               int open_flags, struct iattr *attr, int *opened)
 {
        struct nfs4_state *state;
        struct nfs4_label l = {0, 0, 0, NULL}, *label = NULL;
@@ -2667,7 +2678,7 @@ nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags
        label = nfs4_label_init_security(dir, ctx->dentry, attr, &l);
 
        /* Protect against concurrent sillydeletes */
-       state = nfs4_do_open(dir, ctx, open_flags, attr, label);
+       state = nfs4_do_open(dir, ctx, open_flags, attr, label, opened);
 
        nfs4_label_release_security(label);
 
@@ -3332,6 +3343,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
        struct nfs4_label l, *ilabel = NULL;
        struct nfs_open_context *ctx;
        struct nfs4_state *state;
+       int opened = 0;
        int status = 0;
 
        ctx = alloc_nfs_open_context(dentry, FMODE_READ);
@@ -3341,7 +3353,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
        ilabel = nfs4_label_init_security(dir, dentry, sattr, &l);
 
        sattr->ia_mode &= ~current_umask();
-       state = nfs4_do_open(dir, ctx, flags, sattr, ilabel);
+       state = nfs4_do_open(dir, ctx, flags, sattr, ilabel, &opened);
        if (IS_ERR(state)) {
                status = PTR_ERR(state);
                goto out;
@@ -7564,8 +7576,10 @@ nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
 {
        int err;
        struct page *page;
-       rpc_authflavor_t flavor;
+       rpc_authflavor_t flavor = RPC_AUTH_MAXFLAVOR;
        struct nfs4_secinfo_flavors *flavors;
+       struct nfs4_secinfo4 *secinfo;
+       int i;
 
        page = alloc_page(GFP_KERNEL);
        if (!page) {
@@ -7587,9 +7601,31 @@ nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
        if (err)
                goto out_freepage;
 
-       flavor = nfs_find_best_sec(flavors);
-       if (err == 0)
-               err = nfs4_lookup_root_sec(server, fhandle, info, flavor);
+       for (i = 0; i < flavors->num_flavors; i++) {
+               secinfo = &flavors->flavors[i];
+
+               switch (secinfo->flavor) {
+               case RPC_AUTH_NULL:
+               case RPC_AUTH_UNIX:
+               case RPC_AUTH_GSS:
+                       flavor = rpcauth_get_pseudoflavor(secinfo->flavor,
+                                       &secinfo->flavor_info);
+                       break;
+               default:
+                       flavor = RPC_AUTH_MAXFLAVOR;
+                       break;
+               }
+
+               if (flavor != RPC_AUTH_MAXFLAVOR) {
+                       err = nfs4_lookup_root_sec(server, fhandle,
+                                                  info, flavor);
+                       if (!err)
+                               break;
+               }
+       }
+
+       if (flavor == RPC_AUTH_MAXFLAVOR)
+               err = -EPERM;
 
 out_freepage:
        put_page(page);
index 0ba679866e504ec126720f3eb7b78e210703f538..da276640f7763d2463c0fa99cb832a86d243f10c 100644 (file)
@@ -94,6 +94,7 @@ void nilfs_forget_buffer(struct buffer_head *bh)
        clear_buffer_nilfs_volatile(bh);
        clear_buffer_nilfs_checked(bh);
        clear_buffer_nilfs_redirected(bh);
+       clear_buffer_async_write(bh);
        clear_buffer_dirty(bh);
        if (nilfs_page_buffers_clean(page))
                __nilfs_clear_page_dirty(page);
@@ -429,6 +430,7 @@ void nilfs_clear_dirty_page(struct page *page, bool silent)
                                        "discard block %llu, size %zu",
                                        (u64)bh->b_blocknr, bh->b_size);
                        }
+                       clear_buffer_async_write(bh);
                        clear_buffer_dirty(bh);
                        clear_buffer_nilfs_volatile(bh);
                        clear_buffer_nilfs_checked(bh);
index bd88a7461063bba02f31c6f873902c9c8e87e943..9f6b486b6c01a0e6711ca5930e78474d0739e35e 100644 (file)
@@ -665,7 +665,7 @@ static size_t nilfs_lookup_dirty_data_buffers(struct inode *inode,
 
                bh = head = page_buffers(page);
                do {
-                       if (!buffer_dirty(bh))
+                       if (!buffer_dirty(bh) || buffer_async_write(bh))
                                continue;
                        get_bh(bh);
                        list_add_tail(&bh->b_assoc_buffers, listp);
@@ -699,7 +699,8 @@ static void nilfs_lookup_dirty_node_buffers(struct inode *inode,
                for (i = 0; i < pagevec_count(&pvec); i++) {
                        bh = head = page_buffers(pvec.pages[i]);
                        do {
-                               if (buffer_dirty(bh)) {
+                               if (buffer_dirty(bh) &&
+                                               !buffer_async_write(bh)) {
                                        get_bh(bh);
                                        list_add_tail(&bh->b_assoc_buffers,
                                                      listp);
@@ -1579,6 +1580,7 @@ static void nilfs_segctor_prepare_write(struct nilfs_sc_info *sci)
 
                list_for_each_entry(bh, &segbuf->sb_segsum_buffers,
                                    b_assoc_buffers) {
+                       set_buffer_async_write(bh);
                        if (bh->b_page != bd_page) {
                                if (bd_page) {
                                        lock_page(bd_page);
@@ -1592,6 +1594,7 @@ static void nilfs_segctor_prepare_write(struct nilfs_sc_info *sci)
 
                list_for_each_entry(bh, &segbuf->sb_payload_buffers,
                                    b_assoc_buffers) {
+                       set_buffer_async_write(bh);
                        if (bh == segbuf->sb_super_root) {
                                if (bh->b_page != bd_page) {
                                        lock_page(bd_page);
@@ -1677,6 +1680,7 @@ static void nilfs_abort_logs(struct list_head *logs, int err)
        list_for_each_entry(segbuf, logs, sb_list) {
                list_for_each_entry(bh, &segbuf->sb_segsum_buffers,
                                    b_assoc_buffers) {
+                       clear_buffer_async_write(bh);
                        if (bh->b_page != bd_page) {
                                if (bd_page)
                                        end_page_writeback(bd_page);
@@ -1686,6 +1690,7 @@ static void nilfs_abort_logs(struct list_head *logs, int err)
 
                list_for_each_entry(bh, &segbuf->sb_payload_buffers,
                                    b_assoc_buffers) {
+                       clear_buffer_async_write(bh);
                        if (bh == segbuf->sb_super_root) {
                                if (bh->b_page != bd_page) {
                                        end_page_writeback(bd_page);
@@ -1755,6 +1760,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)
                                    b_assoc_buffers) {
                        set_buffer_uptodate(bh);
                        clear_buffer_dirty(bh);
+                       clear_buffer_async_write(bh);
                        if (bh->b_page != bd_page) {
                                if (bd_page)
                                        end_page_writeback(bd_page);
@@ -1776,6 +1782,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)
                                    b_assoc_buffers) {
                        set_buffer_uptodate(bh);
                        clear_buffer_dirty(bh);
+                       clear_buffer_async_write(bh);
                        clear_buffer_delay(bh);
                        clear_buffer_nilfs_volatile(bh);
                        clear_buffer_nilfs_redirected(bh);
index ef999729e274ead1ed88c699ee86b8011fd5ff77..0d3a97d2d5f659caeb60f20f448ce25371036ff2 100644 (file)
@@ -70,9 +70,10 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, unsigned int flags)
         */
        if (inode == NULL) {
                unsigned long gen = (unsigned long) dentry->d_fsdata;
-               unsigned long pgen =
-                       OCFS2_I(dentry->d_parent->d_inode)->ip_dir_lock_gen;
-
+               unsigned long pgen;
+               spin_lock(&dentry->d_lock);
+               pgen = OCFS2_I(dentry->d_parent->d_inode)->ip_dir_lock_gen;
+               spin_unlock(&dentry->d_lock);
                trace_ocfs2_dentry_revalidate_negative(dentry->d_name.len,
                                                       dentry->d_name.name,
                                                       pgen, gen);
index 121da2dc3be841e579dd64fdea6bcfb89f5c121c..d4e81e4a9b0489de2eb66899eb23b9d87ea81ae5 100644 (file)
@@ -1924,7 +1924,7 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
 {
        int tmp, hangup_needed = 0;
        struct ocfs2_super *osb = NULL;
-       char nodestr[8];
+       char nodestr[12];
 
        trace_ocfs2_dismount_volume(sb);
 
index 2a731b0d08bc456af047ad58ce68c6823f7b1972..d420331ca32a20b20b00c1da468a9af516e6a037 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -744,14 +744,24 @@ cleanup_file:
 
 /**
  * finish_open - finish opening a file
- * @od: opaque open data
+ * @file: file pointer
  * @dentry: pointer to dentry
  * @open: open callback
+ * @opened: state of open
  *
  * This can be used to finish opening a file passed to i_op->atomic_open().
  *
  * If the open callback is set to NULL, then the standard f_op->open()
  * filesystem callback is substituted.
+ *
+ * NB: the dentry reference is _not_ consumed.  If, for example, the dentry is
+ * the return value of d_splice_alias(), then the caller needs to perform dput()
+ * on it after finish_open().
+ *
+ * On successful return @file is a fully instantiated open file.  After this, if
+ * an error occurs in ->atomic_open(), it needs to clean up with fput().
+ *
+ * Returns zero on success or -errno if the open failed.
  */
 int finish_open(struct file *file, struct dentry *dentry,
                int (*open)(struct inode *, struct file *),
@@ -772,11 +782,16 @@ EXPORT_SYMBOL(finish_open);
 /**
  * finish_no_open - finish ->atomic_open() without opening the file
  *
- * @od: opaque open data
+ * @file: file pointer
  * @dentry: dentry or NULL (as returned from ->lookup())
  *
  * This can be used to set the result of a successful lookup in ->atomic_open().
- * The filesystem's atomic_open() method shall return NULL after calling this.
+ *
+ * NB: unlike finish_open() this function does consume the dentry reference and
+ * the caller need not dput() it.
+ *
+ * Returns "1" which must be the return value of ->atomic_open() after having
+ * called this function.
  */
 int finish_no_open(struct file *file, struct dentry *dentry)
 {
index 4ffb7ab5e397ecfcaede608a39c5025cb4ecd858..b8e93a40a5d3342767a26959858d24f2a24274c0 100644 (file)
@@ -168,7 +168,7 @@ static int pstore_decompress(void *in, void *out, size_t inlen, size_t outlen)
        int err, ret;
 
        ret = -EIO;
-       err = zlib_inflateInit(&stream);
+       err = zlib_inflateInit2(&stream, WINDOW_BITS);
        if (err != Z_OK)
                goto error;
 
@@ -195,8 +195,29 @@ error:
 static void allocate_buf_for_compression(void)
 {
        size_t size;
+       size_t cmpr;
+
+       switch (psinfo->bufsize) {
+       /* buffer range for efivars */
+       case 1000 ... 2000:
+               cmpr = 56;
+               break;
+       case 2001 ... 3000:
+               cmpr = 54;
+               break;
+       case 3001 ... 3999:
+               cmpr = 52;
+               break;
+       /* buffer range for nvram, erst */
+       case 4000 ... 10000:
+               cmpr = 45;
+               break;
+       default:
+               cmpr = 60;
+               break;
+       }
 
-       big_oops_buf_sz = (psinfo->bufsize * 100) / 45;
+       big_oops_buf_sz = (psinfo->bufsize * 100) / cmpr;
        big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
        if (big_oops_buf) {
                size = max(zlib_deflate_workspacesize(WINDOW_BITS, MEM_LEVEL),
@@ -295,10 +316,6 @@ static void pstore_dump(struct kmsg_dumper *dumper,
                                compressed = true;
                                total_len = zipped_len;
                        } else {
-                               pr_err("pstore: compression failed for Part %d"
-                                       " returned %d\n", part, zipped_len);
-                               pr_err("pstore: Capture uncompressed"
-                                       " oops/panic report of Part %d\n", part);
                                compressed = false;
                                total_len = copy_kmsg_to_buffer(hsize, len);
                        }
index 73feacc49b2ef3bc2b088f7d74ed05d4195a45ac..fd777032c2ba7551dd10fbf9572289b36d09ad27 100644 (file)
@@ -1163,21 +1163,6 @@ static struct reiserfs_journal_list *find_newer_jl_for_cn(struct
        return NULL;
 }
 
-static int newer_jl_done(struct reiserfs_journal_cnode *cn)
-{
-       struct super_block *sb = cn->sb;
-       b_blocknr_t blocknr = cn->blocknr;
-
-       cn = cn->hprev;
-       while (cn) {
-               if (cn->sb == sb && cn->blocknr == blocknr && cn->jlist &&
-                   atomic_read(&cn->jlist->j_commit_left) != 0)
-                                   return 0;
-               cn = cn->hprev;
-       }
-       return 1;
-}
-
 static void remove_journal_hash(struct super_block *,
                                struct reiserfs_journal_cnode **,
                                struct reiserfs_journal_list *, unsigned long,
@@ -1353,7 +1338,6 @@ static int flush_journal_list(struct super_block *s,
                reiserfs_warning(s, "clm-2048", "called with wcount %d",
                                 atomic_read(&journal->j_wcount));
        }
-       BUG_ON(jl->j_trans_id == 0);
 
        /* if flushall == 0, the lock is already held */
        if (flushall) {
@@ -1593,31 +1577,6 @@ static int flush_journal_list(struct super_block *s,
        return err;
 }
 
-static int test_transaction(struct super_block *s,
-                            struct reiserfs_journal_list *jl)
-{
-       struct reiserfs_journal_cnode *cn;
-
-       if (jl->j_len == 0 || atomic_read(&jl->j_nonzerolen) == 0)
-               return 1;
-
-       cn = jl->j_realblock;
-       while (cn) {
-               /* if the blocknr == 0, this has been cleared from the hash,
-                ** skip it
-                */
-               if (cn->blocknr == 0) {
-                       goto next;
-               }
-               if (cn->bh && !newer_jl_done(cn))
-                       return 0;
-             next:
-               cn = cn->next;
-               cond_resched();
-       }
-       return 0;
-}
-
 static int write_one_transaction(struct super_block *s,
                                 struct reiserfs_journal_list *jl,
                                 struct buffer_chunk *chunk)
@@ -1805,6 +1764,8 @@ static int flush_used_journal_lists(struct super_block *s,
                        break;
                tjl = JOURNAL_LIST_ENTRY(tjl->j_list.next);
        }
+       get_journal_list(jl);
+       get_journal_list(flush_jl);
        /* try to find a group of blocks we can flush across all the
         ** transactions, but only bother if we've actually spanned
         ** across multiple lists
@@ -1813,6 +1774,8 @@ static int flush_used_journal_lists(struct super_block *s,
                ret = kupdate_transactions(s, jl, &tjl, &trans_id, len, i);
        }
        flush_journal_list(s, flush_jl, 1);
+       put_journal_list(s, flush_jl);
+       put_journal_list(s, jl);
        return 0;
 }
 
@@ -3868,27 +3831,6 @@ int reiserfs_prepare_for_journal(struct super_block *sb,
        return 1;
 }
 
-static void flush_old_journal_lists(struct super_block *s)
-{
-       struct reiserfs_journal *journal = SB_JOURNAL(s);
-       struct reiserfs_journal_list *jl;
-       struct list_head *entry;
-       time_t now = get_seconds();
-
-       while (!list_empty(&journal->j_journal_list)) {
-               entry = journal->j_journal_list.next;
-               jl = JOURNAL_LIST_ENTRY(entry);
-               /* this check should always be run, to send old lists to disk */
-               if (jl->j_timestamp < (now - (JOURNAL_MAX_TRANS_AGE * 4)) &&
-                   atomic_read(&jl->j_commit_left) == 0 &&
-                   test_transaction(s, jl)) {
-                       flush_used_journal_lists(s, jl);
-               } else {
-                       break;
-               }
-       }
-}
-
 /*
 ** long and ugly.  If flush, will not return until all commit
 ** blocks and all real buffers in the trans are on disk.
@@ -4232,7 +4174,6 @@ static int do_journal_end(struct reiserfs_transaction_handle *th,
                        }
                }
        }
-       flush_old_journal_lists(sb);
 
        journal->j_current_jl->j_list_bitmap =
            get_list_bitmap(sb, journal->j_current_jl);
index 3a96c9783a8b959015af96e0b0548bd8e51cc606..0225c20f877047abb0a47a856c6099594964b6aa 100644 (file)
@@ -264,6 +264,8 @@ out_free_sb:
  */
 static inline void destroy_super(struct super_block *s)
 {
+       list_lru_destroy(&s->s_dentry_lru);
+       list_lru_destroy(&s->s_inode_lru);
 #ifdef CONFIG_SMP
        free_percpu(s->s_files);
 #endif
@@ -323,8 +325,6 @@ void deactivate_locked_super(struct super_block *s)
 
                /* caches are now gone, we can safely kill the shrinker now */
                unregister_shrinker(&s->s_shrink);
-               list_lru_destroy(&s->s_dentry_lru);
-               list_lru_destroy(&s->s_inode_lru);
 
                put_filesystem(fs);
                put_super(s);
index d0c6a007ce835cf869fac695eb5445b34be6d814..eda10959714f2acad6ce5d9be82fffbe9426513b 100644 (file)
@@ -487,6 +487,7 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
        sbi->s_sb = sb;
        sbi->s_block_base = 0;
        sbi->s_type = FSTYPE_V7;
+       mutex_init(&sbi->s_lock);
        sb->s_fs_info = sbi;
        
        sb_set_blocksize(sb, 512);
index 7e5aae4bf46fd1c1e65da56615238ffe4944fd3b..6eaf5edf1ea1577e88cafc60184963e1b18df5a5 100644 (file)
@@ -30,18 +30,17 @@ void udf_free_inode(struct inode *inode)
 {
        struct super_block *sb = inode->i_sb;
        struct udf_sb_info *sbi = UDF_SB(sb);
+       struct logicalVolIntegrityDescImpUse *lvidiu = udf_sb_lvidiu(sb);
 
-       mutex_lock(&sbi->s_alloc_mutex);
-       if (sbi->s_lvid_bh) {
-               struct logicalVolIntegrityDescImpUse *lvidiu =
-                                                       udf_sb_lvidiu(sbi);
+       if (lvidiu) {
+               mutex_lock(&sbi->s_alloc_mutex);
                if (S_ISDIR(inode->i_mode))
                        le32_add_cpu(&lvidiu->numDirs, -1);
                else
                        le32_add_cpu(&lvidiu->numFiles, -1);
                udf_updated_lvid(sb);
+               mutex_unlock(&sbi->s_alloc_mutex);
        }
-       mutex_unlock(&sbi->s_alloc_mutex);
 
        udf_free_blocks(sb, NULL, &UDF_I(inode)->i_location, 0, 1);
 }
@@ -55,6 +54,7 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err)
        uint32_t start = UDF_I(dir)->i_location.logicalBlockNum;
        struct udf_inode_info *iinfo;
        struct udf_inode_info *dinfo = UDF_I(dir);
+       struct logicalVolIntegrityDescImpUse *lvidiu;
 
        inode = new_inode(sb);
 
@@ -92,12 +92,10 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err)
                return NULL;
        }
 
-       if (sbi->s_lvid_bh) {
-               struct logicalVolIntegrityDescImpUse *lvidiu;
-
+       lvidiu = udf_sb_lvidiu(sb);
+       if (lvidiu) {
                iinfo->i_unique = lvid_get_unique_id(sb);
                mutex_lock(&sbi->s_alloc_mutex);
-               lvidiu = udf_sb_lvidiu(sbi);
                if (S_ISDIR(mode))
                        le32_add_cpu(&lvidiu->numDirs, 1);
                else
index 839a2bad7f45b693db4ed478598b997c42077712..91219385691d8f80d1db9aed3973183bb931a48d 100644 (file)
@@ -94,13 +94,25 @@ static unsigned int udf_count_free(struct super_block *);
 static int udf_statfs(struct dentry *, struct kstatfs *);
 static int udf_show_options(struct seq_file *, struct dentry *);
 
-struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi)
+struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct super_block *sb)
 {
-       struct logicalVolIntegrityDesc *lvid =
-               (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data;
-       __u32 number_of_partitions = le32_to_cpu(lvid->numOfPartitions);
-       __u32 offset = number_of_partitions * 2 *
-                               sizeof(uint32_t)/sizeof(uint8_t);
+       struct logicalVolIntegrityDesc *lvid;
+       unsigned int partnum;
+       unsigned int offset;
+
+       if (!UDF_SB(sb)->s_lvid_bh)
+               return NULL;
+       lvid = (struct logicalVolIntegrityDesc *)UDF_SB(sb)->s_lvid_bh->b_data;
+       partnum = le32_to_cpu(lvid->numOfPartitions);
+       if ((sb->s_blocksize - sizeof(struct logicalVolIntegrityDescImpUse) -
+            offsetof(struct logicalVolIntegrityDesc, impUse)) /
+            (2 * sizeof(uint32_t)) < partnum) {
+               udf_err(sb, "Logical volume integrity descriptor corrupted "
+                       "(numOfPartitions = %u)!\n", partnum);
+               return NULL;
+       }
+       /* The offset is to skip freeSpaceTable and sizeTable arrays */
+       offset = partnum * 2 * sizeof(uint32_t);
        return (struct logicalVolIntegrityDescImpUse *)&(lvid->impUse[offset]);
 }
 
@@ -629,9 +641,10 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
        struct udf_options uopt;
        struct udf_sb_info *sbi = UDF_SB(sb);
        int error = 0;
+       struct logicalVolIntegrityDescImpUse *lvidiu = udf_sb_lvidiu(sb);
 
-       if (sbi->s_lvid_bh) {
-               int write_rev = le16_to_cpu(udf_sb_lvidiu(sbi)->minUDFWriteRev);
+       if (lvidiu) {
+               int write_rev = le16_to_cpu(lvidiu->minUDFWriteRev);
                if (write_rev > UDF_MAX_WRITE_VERSION && !(*flags & MS_RDONLY))
                        return -EACCES;
        }
@@ -1905,11 +1918,12 @@ static void udf_open_lvid(struct super_block *sb)
 
        if (!bh)
                return;
-
-       mutex_lock(&sbi->s_alloc_mutex);
        lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
-       lvidiu = udf_sb_lvidiu(sbi);
+       lvidiu = udf_sb_lvidiu(sb);
+       if (!lvidiu)
+               return;
 
+       mutex_lock(&sbi->s_alloc_mutex);
        lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
        lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
        udf_time_to_disk_stamp(&lvid->recordingDateAndTime,
@@ -1937,10 +1951,12 @@ static void udf_close_lvid(struct super_block *sb)
 
        if (!bh)
                return;
+       lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
+       lvidiu = udf_sb_lvidiu(sb);
+       if (!lvidiu)
+               return;
 
        mutex_lock(&sbi->s_alloc_mutex);
-       lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
-       lvidiu = udf_sb_lvidiu(sbi);
        lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
        lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
        udf_time_to_disk_stamp(&lvid->recordingDateAndTime, CURRENT_TIME);
@@ -2093,15 +2109,19 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 
        if (sbi->s_lvid_bh) {
                struct logicalVolIntegrityDescImpUse *lvidiu =
-                                                       udf_sb_lvidiu(sbi);
-               uint16_t minUDFReadRev = le16_to_cpu(lvidiu->minUDFReadRev);
-               uint16_t minUDFWriteRev = le16_to_cpu(lvidiu->minUDFWriteRev);
-               /* uint16_t maxUDFWriteRev =
-                               le16_to_cpu(lvidiu->maxUDFWriteRev); */
+                                                       udf_sb_lvidiu(sb);
+               uint16_t minUDFReadRev;
+               uint16_t minUDFWriteRev;
 
+               if (!lvidiu) {
+                       ret = -EINVAL;
+                       goto error_out;
+               }
+               minUDFReadRev = le16_to_cpu(lvidiu->minUDFReadRev);
+               minUDFWriteRev = le16_to_cpu(lvidiu->minUDFWriteRev);
                if (minUDFReadRev > UDF_MAX_READ_VERSION) {
                        udf_err(sb, "minUDFReadRev=%x (max is %x)\n",
-                               le16_to_cpu(lvidiu->minUDFReadRev),
+                               minUDFReadRev,
                                UDF_MAX_READ_VERSION);
                        ret = -EINVAL;
                        goto error_out;
@@ -2265,11 +2285,7 @@ static int udf_statfs(struct dentry *dentry, struct kstatfs *buf)
        struct logicalVolIntegrityDescImpUse *lvidiu;
        u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
 
-       if (sbi->s_lvid_bh != NULL)
-               lvidiu = udf_sb_lvidiu(sbi);
-       else
-               lvidiu = NULL;
-
+       lvidiu = udf_sb_lvidiu(sb);
        buf->f_type = UDF_SUPER_MAGIC;
        buf->f_bsize = sb->s_blocksize;
        buf->f_blocks = sbi->s_partmaps[sbi->s_partition].s_partition_len;
index ed401e94aa8c956dd8685ab33f496fc4ea52eec7..1f32c7bd9f57f21fb2859413cacde08b2949fd3a 100644 (file)
@@ -162,7 +162,7 @@ static inline struct udf_sb_info *UDF_SB(struct super_block *sb)
        return sb->s_fs_info;
 }
 
-struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi);
+struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct super_block *sb);
 
 int udf_compute_nr_groups(struct super_block *sb, u32 partition);
 
index 88c5ea75ebf66abd175bdf2d71898380f2aca9a8..f1d85cfc0a54d1cb54ebe95937872127f2e63142 100644 (file)
@@ -628,6 +628,7 @@ xfs_buf_item_unlock(
                else if (aborted) {
                        ASSERT(XFS_FORCED_SHUTDOWN(lip->li_mountp));
                        if (lip->li_flags & XFS_LI_IN_AIL) {
+                               spin_lock(&lip->li_ailp->xa_lock);
                                xfs_trans_ail_delete(lip->li_ailp, lip,
                                                     SHUTDOWN_LOG_IO_ERROR);
                        }
index 069537c845e5cc424ce02bf3cec7838250357a32..20bf8e8002d6fd2733782af97f373ddaf2bcd8d6 100644 (file)
@@ -1224,6 +1224,7 @@ xfs_da3_node_toosmall(
        /* start with smaller blk num */
        forward = nodehdr.forw < nodehdr.back;
        for (i = 0; i < 2; forward = !forward, i++) {
+               struct xfs_da3_icnode_hdr thdr;
                if (forward)
                        blkno = nodehdr.forw;
                else
@@ -1236,10 +1237,10 @@ xfs_da3_node_toosmall(
                        return(error);
 
                node = bp->b_addr;
-               xfs_da3_node_hdr_from_disk(&nodehdr, node);
+               xfs_da3_node_hdr_from_disk(&thdr, node);
                xfs_trans_brelse(state->args->trans, bp);
 
-               if (count - nodehdr.count >= 0)
+               if (count - thdr.count >= 0)
                        break;  /* fits with at least 25% to spare */
        }
        if (i >= 2) {
index 0957aa98b6c0d6bb1fdc3fa23161d761aeb58567..12dad188939df2e29c4420574bd20bfb319aae35 100644 (file)
@@ -1158,7 +1158,7 @@ xfs_dir2_sf_to_block(
        /*
         * Create entry for .
         */
-       dep = xfs_dir3_data_dot_entry_p(hdr);
+       dep = xfs_dir3_data_dot_entry_p(mp, hdr);
        dep->inumber = cpu_to_be64(dp->i_ino);
        dep->namelen = 1;
        dep->name[0] = '.';
@@ -1172,7 +1172,7 @@ xfs_dir2_sf_to_block(
        /*
         * Create entry for ..
         */
-       dep = xfs_dir3_data_dotdot_entry_p(hdr);
+       dep = xfs_dir3_data_dotdot_entry_p(mp, hdr);
        dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp));
        dep->namelen = 2;
        dep->name[0] = dep->name[1] = '.';
@@ -1183,7 +1183,7 @@ xfs_dir2_sf_to_block(
        blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot);
        blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
                                (char *)dep - (char *)hdr));
-       offset = xfs_dir3_data_first_offset(hdr);
+       offset = xfs_dir3_data_first_offset(mp);
        /*
         * Loop over existing entries, stuff them in.
         */
index a0961a61ac1a9a419fd537cd47dbb7337fbbc3a0..9cf67381adf6769d0b6fc984b6fe5ecaf8cef5b4 100644 (file)
@@ -497,69 +497,58 @@ xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr)
 /*
  * Offsets of . and .. in data space (always block 0)
  *
- * The macros are used for shortform directories as they have no headers to read
- * the magic number out of. Shortform directories need to know the size of the
- * data block header because the sfe embeds the block offset of the entry into
- * it so that it doesn't change when format conversion occurs. Bad Things Happen
- * if we don't follow this rule.
- *
  * XXX: there is scope for significant optimisation of the logic here. Right
  * now we are checking for "dir3 format" over and over again. Ideally we should
  * only do it once for each operation.
  */
-#define        XFS_DIR3_DATA_DOT_OFFSET(mp)    \
-       xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&(mp)->m_sb))
-#define        XFS_DIR3_DATA_DOTDOT_OFFSET(mp) \
-       (XFS_DIR3_DATA_DOT_OFFSET(mp) + xfs_dir3_data_entsize(mp, 1))
-#define        XFS_DIR3_DATA_FIRST_OFFSET(mp)          \
-       (XFS_DIR3_DATA_DOTDOT_OFFSET(mp) + xfs_dir3_data_entsize(mp, 2))
-
 static inline xfs_dir2_data_aoff_t
-xfs_dir3_data_dot_offset(struct xfs_dir2_data_hdr *hdr)
+xfs_dir3_data_dot_offset(struct xfs_mount *mp)
 {
-       return xfs_dir3_data_entry_offset(hdr);
+       return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
 }
 
 static inline xfs_dir2_data_aoff_t
-xfs_dir3_data_dotdot_offset(struct xfs_dir2_data_hdr *hdr)
+xfs_dir3_data_dotdot_offset(struct xfs_mount *mp)
 {
-       bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
-                   hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
-       return xfs_dir3_data_dot_offset(hdr) +
-               __xfs_dir3_data_entsize(dir3, 1);
+       return xfs_dir3_data_dot_offset(mp) +
+               xfs_dir3_data_entsize(mp, 1);
 }
 
 static inline xfs_dir2_data_aoff_t
-xfs_dir3_data_first_offset(struct xfs_dir2_data_hdr *hdr)
+xfs_dir3_data_first_offset(struct xfs_mount *mp)
 {
-       bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
-                   hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
-       return xfs_dir3_data_dotdot_offset(hdr) +
-               __xfs_dir3_data_entsize(dir3, 2);
+       return xfs_dir3_data_dotdot_offset(mp) +
+               xfs_dir3_data_entsize(mp, 2);
 }
 
 /*
  * location of . and .. in data space (always block 0)
  */
 static inline struct xfs_dir2_data_entry *
-xfs_dir3_data_dot_entry_p(struct xfs_dir2_data_hdr *hdr)
+xfs_dir3_data_dot_entry_p(
+       struct xfs_mount        *mp,
+       struct xfs_dir2_data_hdr *hdr)
 {
        return (struct xfs_dir2_data_entry *)
-               ((char *)hdr + xfs_dir3_data_dot_offset(hdr));
+               ((char *)hdr + xfs_dir3_data_dot_offset(mp));
 }
 
 static inline struct xfs_dir2_data_entry *
-xfs_dir3_data_dotdot_entry_p(struct xfs_dir2_data_hdr *hdr)
+xfs_dir3_data_dotdot_entry_p(
+       struct xfs_mount        *mp,
+       struct xfs_dir2_data_hdr *hdr)
 {
        return (struct xfs_dir2_data_entry *)
-               ((char *)hdr + xfs_dir3_data_dotdot_offset(hdr));
+               ((char *)hdr + xfs_dir3_data_dotdot_offset(mp));
 }
 
 static inline struct xfs_dir2_data_entry *
-xfs_dir3_data_first_entry_p(struct xfs_dir2_data_hdr *hdr)
+xfs_dir3_data_first_entry_p(
+       struct xfs_mount        *mp,
+       struct xfs_dir2_data_hdr *hdr)
 {
        return (struct xfs_dir2_data_entry *)
-               ((char *)hdr + xfs_dir3_data_first_offset(hdr));
+               ((char *)hdr + xfs_dir3_data_first_offset(mp));
 }
 
 /*
index 8993ec17452cd7bd62794e71585ea003badad0c0..8f84153e98a8c0f52e27aa9a0a1352779e29e61e 100644 (file)
@@ -119,9 +119,9 @@ xfs_dir2_sf_getdents(
         * mp->m_dirdatablk.
         */
        dot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
-                                            XFS_DIR3_DATA_DOT_OFFSET(mp));
+                                            xfs_dir3_data_dot_offset(mp));
        dotdot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
-                                               XFS_DIR3_DATA_DOTDOT_OFFSET(mp));
+                                               xfs_dir3_data_dotdot_offset(mp));
 
        /*
         * Put . entry unless we're starting past it.
index bb6e2848f473d024d5ff1dd70a1232443901ea9f..3ef6d402084ccf9dabc622ee5db22b41170e3e54 100644 (file)
@@ -557,7 +557,7 @@ xfs_dir2_sf_addname_hard(
         * to insert the new entry.
         * If it's going to end up at the end then oldsfep will point there.
         */
-       for (offset = XFS_DIR3_DATA_FIRST_OFFSET(mp),
+       for (offset = xfs_dir3_data_first_offset(mp),
              oldsfep = xfs_dir2_sf_firstentry(oldsfp),
              add_datasize = xfs_dir3_data_entsize(mp, args->namelen),
              eof = (char *)oldsfep == &buf[old_isize];
@@ -640,7 +640,7 @@ xfs_dir2_sf_addname_pick(
 
        sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
        size = xfs_dir3_data_entsize(mp, args->namelen);
-       offset = XFS_DIR3_DATA_FIRST_OFFSET(mp);
+       offset = xfs_dir3_data_first_offset(mp);
        sfep = xfs_dir2_sf_firstentry(sfp);
        holefit = 0;
        /*
@@ -713,7 +713,7 @@ xfs_dir2_sf_check(
        mp = dp->i_mount;
 
        sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
-       offset = XFS_DIR3_DATA_FIRST_OFFSET(mp);
+       offset = xfs_dir3_data_first_offset(mp);
        ino = xfs_dir2_sf_get_parent_ino(sfp);
        i8count = ino > XFS_DIR2_MAX_SHORT_INUM;
 
index 71520e6e5d65048c04996133621b2916653b5c31..1ee776d477c3d1b240378993f946e9716f62c83d 100644 (file)
@@ -64,7 +64,8 @@ int xfs_dqerror_mod = 33;
 struct kmem_zone               *xfs_qm_dqtrxzone;
 static struct kmem_zone                *xfs_qm_dqzone;
 
-static struct lock_class_key xfs_dquot_other_class;
+static struct lock_class_key xfs_dquot_group_class;
+static struct lock_class_key xfs_dquot_project_class;
 
 /*
  * This is called to free all the memory associated with a dquot
@@ -703,8 +704,20 @@ xfs_qm_dqread(
         * Make sure group quotas have a different lock class than user
         * quotas.
         */
-       if (!(type & XFS_DQ_USER))
-               lockdep_set_class(&dqp->q_qlock, &xfs_dquot_other_class);
+       switch (type) {
+       case XFS_DQ_USER:
+               /* uses the default lock class */
+               break;
+       case XFS_DQ_GROUP:
+               lockdep_set_class(&dqp->q_qlock, &xfs_dquot_group_class);
+               break;
+       case XFS_DQ_PROJ:
+               lockdep_set_class(&dqp->q_qlock, &xfs_dquot_project_class);
+               break;
+       default:
+               ASSERT(0);
+               break;
+       }
 
        XFS_STATS_INC(xs_qm_dquot);
 
index 1edb5cc3e5f495fdca3059054d1f2e7bd5d9fd58..18272c766a508ab53deb5465448ca26bf02110d6 100644 (file)
@@ -515,7 +515,7 @@ typedef struct xfs_swapext
 /*     XFS_IOC_GETBIOSIZE ---- deprecated 47      */
 #define XFS_IOC_GETBMAPX       _IOWR('X', 56, struct getbmap)
 #define XFS_IOC_ZERO_RANGE     _IOW ('X', 57, struct xfs_flock64)
-#define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_eofblocks)
+#define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_fs_eofblocks)
 
 /*
  * ioctl commands that replace IRIX syssgi()'s
index 193206ba43582c0aecbea7afd1d23220bfff554f..474807a401c864e7681d3f8d0f111358c45536fc 100644 (file)
@@ -119,11 +119,6 @@ xfs_inode_free(
                ip->i_itemp = NULL;
        }
 
-       /* asserts to verify all state is correct here */
-       ASSERT(atomic_read(&ip->i_pincount) == 0);
-       ASSERT(!spin_is_locked(&ip->i_flags_lock));
-       ASSERT(!xfs_isiflocked(ip));
-
        /*
         * Because we use RCU freeing we need to ensure the inode always
         * appears to be reclaimed with an invalid inode number when in the
@@ -135,6 +130,10 @@ xfs_inode_free(
        ip->i_ino = 0;
        spin_unlock(&ip->i_flags_lock);
 
+       /* asserts to verify all state is correct here */
+       ASSERT(atomic_read(&ip->i_pincount) == 0);
+       ASSERT(!xfs_isiflocked(ip));
+
        call_rcu(&VFS_I(ip)->i_rcu, xfs_inode_free_callback);
 }
 
index dabda9521b4becc2ded846307aa062a093a7a3d3..39797490a1f1996e3f92f51efb532f15a75da8fa 100644 (file)
@@ -1585,6 +1585,7 @@ xlog_recover_add_to_trans(
                "bad number of regions (%d) in inode log format",
                                  in_f->ilf_size);
                        ASSERT(0);
+                       kmem_free(ptr);
                        return XFS_ERROR(EIO);
                }
 
@@ -1970,6 +1971,13 @@ xlog_recover_do_inode_buffer(
  * magic number.  If we don't recognise the magic number in the buffer, then
  * return a LSN of -1 so that the caller knows it was an unrecognised block and
  * so can recover the buffer.
+ *
+ * Note: we cannot rely solely on magic number matches to determine that the
+ * buffer has a valid LSN - we also need to verify that it belongs to this
+ * filesystem, so we need to extract the object's LSN and compare it to that
+ * which we read from the superblock. If the UUIDs don't match, then we've got a
+ * stale metadata block from an old filesystem instance that we need to recover
+ * over the top of.
  */
 static xfs_lsn_t
 xlog_recover_get_buf_lsn(
@@ -1980,6 +1988,8 @@ xlog_recover_get_buf_lsn(
        __uint16_t              magic16;
        __uint16_t              magicda;
        void                    *blk = bp->b_addr;
+       uuid_t                  *uuid;
+       xfs_lsn_t               lsn = -1;
 
        /* v4 filesystems always recover immediately */
        if (!xfs_sb_version_hascrc(&mp->m_sb))
@@ -1992,43 +2002,79 @@ xlog_recover_get_buf_lsn(
        case XFS_ABTB_MAGIC:
        case XFS_ABTC_MAGIC:
        case XFS_IBT_CRC_MAGIC:
-       case XFS_IBT_MAGIC:
-               return be64_to_cpu(
-                               ((struct xfs_btree_block *)blk)->bb_u.s.bb_lsn);
+       case XFS_IBT_MAGIC: {
+               struct xfs_btree_block *btb = blk;
+
+               lsn = be64_to_cpu(btb->bb_u.s.bb_lsn);
+               uuid = &btb->bb_u.s.bb_uuid;
+               break;
+       }
        case XFS_BMAP_CRC_MAGIC:
-       case XFS_BMAP_MAGIC:
-               return be64_to_cpu(
-                               ((struct xfs_btree_block *)blk)->bb_u.l.bb_lsn);
+       case XFS_BMAP_MAGIC: {
+               struct xfs_btree_block *btb = blk;
+
+               lsn = be64_to_cpu(btb->bb_u.l.bb_lsn);
+               uuid = &btb->bb_u.l.bb_uuid;
+               break;
+       }
        case XFS_AGF_MAGIC:
-               return be64_to_cpu(((struct xfs_agf *)blk)->agf_lsn);
+               lsn = be64_to_cpu(((struct xfs_agf *)blk)->agf_lsn);
+               uuid = &((struct xfs_agf *)blk)->agf_uuid;
+               break;
        case XFS_AGFL_MAGIC:
-               return be64_to_cpu(((struct xfs_agfl *)blk)->agfl_lsn);
+               lsn = be64_to_cpu(((struct xfs_agfl *)blk)->agfl_lsn);
+               uuid = &((struct xfs_agfl *)blk)->agfl_uuid;
+               break;
        case XFS_AGI_MAGIC:
-               return be64_to_cpu(((struct xfs_agi *)blk)->agi_lsn);
+               lsn = be64_to_cpu(((struct xfs_agi *)blk)->agi_lsn);
+               uuid = &((struct xfs_agi *)blk)->agi_uuid;
+               break;
        case XFS_SYMLINK_MAGIC:
-               return be64_to_cpu(((struct xfs_dsymlink_hdr *)blk)->sl_lsn);
+               lsn = be64_to_cpu(((struct xfs_dsymlink_hdr *)blk)->sl_lsn);
+               uuid = &((struct xfs_dsymlink_hdr *)blk)->sl_uuid;
+               break;
        case XFS_DIR3_BLOCK_MAGIC:
        case XFS_DIR3_DATA_MAGIC:
        case XFS_DIR3_FREE_MAGIC:
-               return be64_to_cpu(((struct xfs_dir3_blk_hdr *)blk)->lsn);
+               lsn = be64_to_cpu(((struct xfs_dir3_blk_hdr *)blk)->lsn);
+               uuid = &((struct xfs_dir3_blk_hdr *)blk)->uuid;
+               break;
        case XFS_ATTR3_RMT_MAGIC:
-               return be64_to_cpu(((struct xfs_attr3_rmt_hdr *)blk)->rm_lsn);
+               lsn = be64_to_cpu(((struct xfs_attr3_rmt_hdr *)blk)->rm_lsn);
+               uuid = &((struct xfs_attr3_rmt_hdr *)blk)->rm_uuid;
+               break;
        case XFS_SB_MAGIC:
-               return be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn);
+               lsn = be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn);
+               uuid = &((struct xfs_dsb *)blk)->sb_uuid;
+               break;
        default:
                break;
        }
 
+       if (lsn != (xfs_lsn_t)-1) {
+               if (!uuid_equal(&mp->m_sb.sb_uuid, uuid))
+                       goto recover_immediately;
+               return lsn;
+       }
+
        magicda = be16_to_cpu(((struct xfs_da_blkinfo *)blk)->magic);
        switch (magicda) {
        case XFS_DIR3_LEAF1_MAGIC:
        case XFS_DIR3_LEAFN_MAGIC:
        case XFS_DA3_NODE_MAGIC:
-               return be64_to_cpu(((struct xfs_da3_blkinfo *)blk)->lsn);
+               lsn = be64_to_cpu(((struct xfs_da3_blkinfo *)blk)->lsn);
+               uuid = &((struct xfs_da3_blkinfo *)blk)->uuid;
+               break;
        default:
                break;
        }
 
+       if (lsn != (xfs_lsn_t)-1) {
+               if (!uuid_equal(&mp->m_sb.sb_uuid, uuid))
+                       goto recover_immediately;
+               return lsn;
+       }
+
        /*
         * We do individual object checks on dquot and inode buffers as they
         * have their own individual LSN records. Also, we could have a stale
index d06079c774a081e5a5f467da8cb4680c9d23054e..99b490b4d05aa5cff749937f3a3a69a5c3406f92 100644 (file)
@@ -6,12 +6,12 @@ static inline pte_t mk_huge_pte(struct page *page, pgprot_t pgprot)
        return mk_pte(page, pgprot);
 }
 
-static inline int huge_pte_write(pte_t pte)
+static inline unsigned long huge_pte_write(pte_t pte)
 {
        return pte_write(pte);
 }
 
-static inline int huge_pte_dirty(pte_t pte)
+static inline unsigned long huge_pte_dirty(pte_t pte)
 {
        return pte_dirty(pte);
 }
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b1a49677fe2540e93aae3b40b1c235949ac756cf 100644 (file)
@@ -0,0 +1 @@
+/* no content, but patch(1) dislikes empty files */
index 290734191f72d85a855022a2f0e24e7a6c895ffb..b46fb45f2cca4a5881b64d93577e6ae03a221670 100644 (file)
@@ -1322,10 +1322,9 @@ extern int drm_newctx(struct drm_device *dev, void *data,
 extern int drm_rmctx(struct drm_device *dev, void *data,
                     struct drm_file *file_priv);
 
-extern void drm_legacy_ctxbitmap_init(struct drm_device *dev);
-extern void drm_legacy_ctxbitmap_cleanup(struct drm_device *dev);
-extern void drm_legacy_ctxbitmap_release(struct drm_device *dev,
-                                        struct drm_file *file_priv);
+extern int drm_ctxbitmap_init(struct drm_device *dev);
+extern void drm_ctxbitmap_cleanup(struct drm_device *dev);
+extern void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle);
 
 extern int drm_setsareactx(struct drm_device *dev, void *data,
                           struct drm_file *file_priv);
index fd54a14a7c2a23972f4074217265c3e767063feb..3d79e513c0b3663ef9cd08850801a2d038ee721d 100644 (file)
        {0x1002, 0x130F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x1310, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x1311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x1312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x1313, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x1315, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x1316, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x1317, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x131B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x131C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x131D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
        {0x1002, 0x3151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
index 43ec7e247a8086972ae7ef0e87efde66dd4ac0e7..682df0e1954a96718ae1e439db73441681101145 100644 (file)
@@ -30,7 +30,6 @@ struct amba_device {
        struct device           dev;
        struct resource         res;
        struct clk              *pclk;
-       u64                     dma_mask;
        unsigned int            periphid;
        unsigned int            irq[AMBA_NR_IRQS];
 };
@@ -131,7 +130,6 @@ struct amba_device name##_device = {                                \
 struct amba_device name##_device = {                           \
        .dev = __AMBA_DEV(busid, data, ~0ULL),                  \
        .res = DEFINE_RES_MEM(base, SZ_4K),                     \
-       .dma_mask = ~0ULL,                                      \
        .irq = irqs,                                            \
        .periphid = id,                                         \
 }
index f7f1d7169b11c332612ba09a1663141870e08849..089743ade734fc564e18bfa7be35608da68d6fde 100644 (file)
@@ -158,6 +158,26 @@ static inline bool balloon_page_movable(struct page *page)
        return false;
 }
 
+/*
+ * isolated_balloon_page - identify an isolated balloon page on private
+ *                        compaction/migration page lists.
+ *
+ * After a compaction thread isolates a balloon page for migration, it raises
+ * the page refcount to prevent concurrent compaction threads from re-isolating
+ * the same page. For that reason putback_movable_pages(), or other routines
+ * that need to identify isolated balloon pages on private pagelists, cannot
+ * rely on balloon_page_movable() to accomplish the task.
+ */
+static inline bool isolated_balloon_page(struct page *page)
+{
+       /* Already isolated balloon pages, by default, have a raised refcount */
+       if (page_flags_cleared(page) && !page_mapped(page) &&
+           page_count(page) >= 2)
+               return __is_movable_balloon_page(page);
+
+       return false;
+}
+
 /*
  * balloon_page_insert - insert a page into the balloon's page list and make
  *                      the page->mapping assignment accordingly.
@@ -243,6 +263,11 @@ static inline bool balloon_page_movable(struct page *page)
        return false;
 }
 
+static inline bool isolated_balloon_page(struct page *page)
+{
+       return false;
+}
+
 static inline bool balloon_page_isolate(struct page *page)
 {
        return false;
index d66033f418c98bf1818ba2c5fcbdc7bcebe8021b..0333e605ea0d752c5aa306957a80aa72c5d4094f 100644 (file)
@@ -242,6 +242,7 @@ extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
                                 struct bcma_device *core, bool enable);
 extern void bcma_core_pci_up(struct bcma_bus *bus);
 extern void bcma_core_pci_down(struct bcma_bus *bus);
+extern void bcma_core_pci_power_save(struct bcma_bus *bus, bool up);
 
 extern int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev);
 extern int bcma_core_pci_plat_dev_init(struct pci_dev *dev);
index 2fdb4a451b49bd626d9415b231c76b7ac927cf69..0e6f765aa1f5adf3acbf54e27cea6fbe495de1cb 100644 (file)
@@ -862,6 +862,17 @@ static inline unsigned int blk_rq_get_max_sectors(struct request *rq)
        return blk_queue_get_max_sectors(q, rq->cmd_flags);
 }
 
+static inline unsigned int blk_rq_count_bios(struct request *rq)
+{
+       unsigned int nr_bios = 0;
+       struct bio *bio;
+
+       __rq_for_each_bio(bio, rq)
+               nr_bios++;
+
+       return nr_bios;
+}
+
 /*
  * Request issue related functions.
  */
index ce6df39f60ff6f966144855ca0e1bdb04c312903..8f47625a06615dbf5cbc79ef5df2e2fd5cee6041 100644 (file)
@@ -335,6 +335,8 @@ extern int ceph_osdc_wait_request(struct ceph_osd_client *osdc,
                                  struct ceph_osd_request *req);
 extern void ceph_osdc_sync(struct ceph_osd_client *osdc);
 
+extern void ceph_osdc_flush_notifies(struct ceph_osd_client *osdc);
+
 extern int ceph_osdc_readpages(struct ceph_osd_client *osdc,
                               struct ceph_vino vino,
                               struct ceph_file_layout *layout,
index 653073de09e379ef1c8b04c1a96d0ef2c948f5a3..ed419c62dde1876f4561179b6b4bc3052a50ed14 100644 (file)
@@ -406,13 +406,14 @@ int dm_noflush_suspending(struct dm_target *ti);
 union map_info *dm_get_mapinfo(struct bio *bio);
 union map_info *dm_get_rq_mapinfo(struct request *rq);
 
+struct queue_limits *dm_get_queue_limits(struct mapped_device *md);
+
 /*
  * Geometry functions.
  */
 int dm_get_geometry(struct mapped_device *md, struct hd_geometry *geo);
 int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo);
 
-
 /*-----------------------------------------------------------------
  * Functions for manipulating device-mapper tables.
  *---------------------------------------------------------------*/
index 3a8d0a2af6077b45acc0126f7f6c57a3661caf7f..fd4aee29ad10caa5bd8073a31c7827baa85d11ae 100644 (file)
@@ -97,6 +97,30 @@ static inline int dma_set_coherent_mask(struct device *dev, u64 mask)
 }
 #endif
 
+/*
+ * Set both the DMA mask and the coherent DMA mask to the same thing.
+ * Note that we don't check the return value from dma_set_coherent_mask()
+ * as the DMA API guarantees that the coherent DMA mask can be set to
+ * the same or smaller than the streaming DMA mask.
+ */
+static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask)
+{
+       int rc = dma_set_mask(dev, mask);
+       if (rc == 0)
+               dma_set_coherent_mask(dev, mask);
+       return rc;
+}
+
+/*
+ * Similar to the above, except it deals with the case where the device
+ * does not have dev->dma_mask appropriately setup.
+ */
+static inline int dma_coerce_mask_and_coherent(struct device *dev, u64 mask)
+{
+       dev->dma_mask = &dev->coherent_dma_mask;
+       return dma_set_mask_and_coherent(dev, mask);
+}
+
 extern u64 dma_get_required_mask(struct device *dev);
 
 static inline unsigned int dma_get_max_seg_size(struct device *dev)
@@ -129,6 +153,13 @@ static inline int dma_set_seg_boundary(struct device *dev, unsigned long mask)
                return -EIO;
 }
 
+#ifndef dma_max_pfn
+static inline unsigned long dma_max_pfn(struct device *dev)
+{
+       return *dev->dma_mask >> PAGE_SHIFT;
+}
+#endif
+
 static inline void *dma_zalloc_coherent(struct device *dev, size_t size,
                                        dma_addr_t *dma_handle, gfp_t flag)
 {
index ee1ffc5e19c9fd3d8b2c9ab4c481953455417d4c..31b9d299ef6ca25bf3d5bfd753860d7d3294be68 100644 (file)
@@ -756,6 +756,10 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags);
 struct hid_device *hid_allocate_device(void);
 struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
 int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
+struct hid_report *hid_validate_values(struct hid_device *hid,
+                                      unsigned int type, unsigned int id,
+                                      unsigned int field_index,
+                                      unsigned int report_counts);
 int hid_open_report(struct hid_device *device);
 int hid_check_keys_pressed(struct hid_device *hid);
 int hid_connect(struct hid_device *hid, unsigned int connect_mask);
index a3b8b2e2d24438129df020cc8d7af78562123cad..d98503bde7e9bc7ace0e2c3ddc5f2ae019f527ff 100644 (file)
 /*
  * Framework version for util services.
  */
+#define UTIL_FW_MINOR  0
+
+#define UTIL_WS2K8_FW_MAJOR  1
+#define UTIL_WS2K8_FW_VERSION     (UTIL_WS2K8_FW_MAJOR << 16 | UTIL_FW_MINOR)
 
 #define UTIL_FW_MAJOR  3
-#define UTIL_FW_MINOR  0
-#define UTIL_FW_MAJOR_MINOR     (UTIL_FW_MAJOR << 16 | UTIL_FW_MINOR)
+#define UTIL_FW_VERSION     (UTIL_FW_MAJOR << 16 | UTIL_FW_MINOR)
 
 
 /*
index 78e2ada50cd5a95c7b7527777a870428afa5352c..d380c5e680086ec4627c745f86dc197e7110ea58 100644 (file)
@@ -55,7 +55,7 @@
 #define DMAR_IQT_REG   0x88    /* Invalidation queue tail register */
 #define DMAR_IQ_SHIFT  4       /* Invalidation queue head/tail shift */
 #define DMAR_IQA_REG   0x90    /* Invalidation queue addr register */
-#define DMAR_ICS_REG   0x98    /* Invalidation complete status register */
+#define DMAR_ICS_REG   0x9c    /* Invalidation complete status register */
 #define DMAR_IRTA_REG  0xb8    /* Interrupt remapping table addr register */
 
 #define OFFSET_STRIDE          (9)
index 0e5d9ecdb2b672d901b47f184a4b720e604317e2..cac496b1e279293164066ea0204c87309169bd49 100644 (file)
@@ -31,6 +31,8 @@
 #define GIC_DIST_TARGET                        0x800
 #define GIC_DIST_CONFIG                        0xc00
 #define GIC_DIST_SOFTINT               0xf00
+#define GIC_DIST_SGI_PENDING_CLEAR     0xf10
+#define GIC_DIST_SGI_PENDING_SET       0xf20
 
 #define GICH_HCR                       0x0
 #define GICH_VTR                       0x4
@@ -74,6 +76,11 @@ static inline void gic_init(unsigned int nr, int start,
        gic_init_bases(nr, start, dist, cpu, 0, NULL);
 }
 
+void gic_send_sgi(unsigned int cpu_id, unsigned int irq);
+int gic_get_cpu_id(unsigned int cpu);
+void gic_migrate_target(unsigned int new_cpu_id);
+unsigned long gic_get_sgir_physaddr(void);
+
 #endif /* __ASSEMBLY */
 
 #endif
index 482ad2d84a32dae333c74cccb2d1394b247d5ae8..672ddc4de4af0511b20a4d269bcae1c517c3d5c4 100644 (file)
@@ -439,6 +439,17 @@ static inline char *hex_byte_pack(char *buf, u8 byte)
        return buf;
 }
 
+extern const char hex_asc_upper[];
+#define hex_asc_upper_lo(x)    hex_asc_upper[((x) & 0x0f)]
+#define hex_asc_upper_hi(x)    hex_asc_upper[((x) & 0xf0) >> 4]
+
+static inline char *hex_byte_pack_upper(char *buf, u8 byte)
+{
+       *buf++ = hex_asc_upper_hi(byte);
+       *buf++ = hex_asc_upper_lo(byte);
+       return buf;
+}
+
 static inline char * __deprecated pack_hex_byte(char *buf, u8 byte)
 {
        return hex_byte_pack(buf, byte);
index ca645a01d37a79767baccfd12a8871b79af7b624..0fbbc7aa02cb17c9c7d1cc5b5a17330d58858c10 100644 (file)
@@ -533,6 +533,7 @@ int gfn_to_page_many_atomic(struct kvm *kvm, gfn_t gfn, struct page **pages,
 
 struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn);
 unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn);
+unsigned long gfn_to_hva_prot(struct kvm *kvm, gfn_t gfn, bool *writable);
 unsigned long gfn_to_hva_memslot(struct kvm_memory_slot *slot, gfn_t gfn);
 void kvm_release_page_clean(struct page *page);
 void kvm_release_page_dirty(struct page *page);
index 60e95872da2983365300f1abb193b6e81974b5de..ecc82b37c4ccf00fb863ecf6981de19bbccec52a 100644 (file)
@@ -53,23 +53,6 @@ struct mem_cgroup_reclaim_cookie {
        unsigned int generation;
 };
 
-enum mem_cgroup_filter_t {
-       VISIT,          /* visit current node */
-       SKIP,           /* skip the current node and continue traversal */
-       SKIP_TREE,      /* skip the whole subtree and continue traversal */
-};
-
-/*
- * mem_cgroup_filter_t predicate might instruct mem_cgroup_iter_cond how to
- * iterate through the hierarchy tree. Each tree element is checked by the
- * predicate before it is returned by the iterator. If a filter returns
- * SKIP or SKIP_TREE then the iterator code continues traversal (with the
- * next node down the hierarchy or the next node that doesn't belong under the
- * memcg's subtree).
- */
-typedef enum mem_cgroup_filter_t
-(*mem_cgroup_iter_filter)(struct mem_cgroup *memcg, struct mem_cgroup *root);
-
 #ifdef CONFIG_MEMCG
 /*
  * All "charge" functions with gfp_mask should use GFP_KERNEL or
@@ -137,18 +120,9 @@ mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
 extern void mem_cgroup_end_migration(struct mem_cgroup *memcg,
        struct page *oldpage, struct page *newpage, bool migration_ok);
 
-struct mem_cgroup *mem_cgroup_iter_cond(struct mem_cgroup *root,
-                                  struct mem_cgroup *prev,
-                                  struct mem_cgroup_reclaim_cookie *reclaim,
-                                  mem_cgroup_iter_filter cond);
-
-static inline struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root,
-                                  struct mem_cgroup *prev,
-                                  struct mem_cgroup_reclaim_cookie *reclaim)
-{
-       return mem_cgroup_iter_cond(root, prev, reclaim, NULL);
-}
-
+struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *,
+                                  struct mem_cgroup *,
+                                  struct mem_cgroup_reclaim_cookie *);
 void mem_cgroup_iter_break(struct mem_cgroup *, struct mem_cgroup *);
 
 /*
@@ -260,9 +234,9 @@ static inline void mem_cgroup_dec_page_stat(struct page *page,
        mem_cgroup_update_page_stat(page, idx, -1);
 }
 
-enum mem_cgroup_filter_t
-mem_cgroup_soft_reclaim_eligible(struct mem_cgroup *memcg,
-               struct mem_cgroup *root);
+unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
+                                               gfp_t gfp_mask,
+                                               unsigned long *total_scanned);
 
 void __mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx);
 static inline void mem_cgroup_count_vm_event(struct mm_struct *mm,
@@ -376,15 +350,6 @@ static inline void mem_cgroup_end_migration(struct mem_cgroup *memcg,
                struct page *oldpage, struct page *newpage, bool migration_ok)
 {
 }
-static inline struct mem_cgroup *
-mem_cgroup_iter_cond(struct mem_cgroup *root,
-               struct mem_cgroup *prev,
-               struct mem_cgroup_reclaim_cookie *reclaim,
-               mem_cgroup_iter_filter cond)
-{
-       /* first call must return non-NULL, second return NULL */
-       return (struct mem_cgroup *)(unsigned long)!prev;
-}
 
 static inline struct mem_cgroup *
 mem_cgroup_iter(struct mem_cgroup *root,
@@ -471,11 +436,11 @@ static inline void mem_cgroup_dec_page_stat(struct page *page,
 }
 
 static inline
-enum mem_cgroup_filter_t
-mem_cgroup_soft_reclaim_eligible(struct mem_cgroup *memcg,
-               struct mem_cgroup *root)
+unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
+                                           gfp_t gfp_mask,
+                                           unsigned long *total_scanned)
 {
-       return VISIT;
+       return 0;
 }
 
 static inline void mem_cgroup_split_huge_fixup(struct page *head)
index ccd4260834c57da2ea30fc5b20714ef15afe076f..bab49da8a0f0b1bd2e01d516fdd0e39a07162326 100644 (file)
@@ -15,8 +15,8 @@
 #include <linux/spinlock_types.h>
 #include <linux/linkage.h>
 #include <linux/lockdep.h>
-
 #include <linux/atomic.h>
+#include <asm/processor.h>
 
 /*
  * Simple, straightforward mutexes with strict semantics:
@@ -175,8 +175,8 @@ extern void mutex_unlock(struct mutex *lock);
 
 extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock);
 
-#ifndef CONFIG_HAVE_ARCH_MUTEX_CPU_RELAX
-#define arch_mutex_cpu_relax() cpu_relax()
+#ifndef arch_mutex_cpu_relax
+# define arch_mutex_cpu_relax() cpu_relax()
 #endif
 
 #endif
index 041b42a305f6a1817df51bfd46aa746a454e1a50..3de49aca451970a738b5ae55cfd74656248ac9ea 100644 (file)
@@ -950,14 +950,14 @@ struct netdev_phys_port_id {
  *     multiple net devices on single physical port.
  *
  * void (*ndo_add_vxlan_port)(struct  net_device *dev,
- *                           sa_family_t sa_family, __u16 port);
+ *                           sa_family_t sa_family, __be16 port);
  *     Called by vxlan to notiy a driver about the UDP port and socket
  *     address family that vxlan is listnening to. It is called only when
  *     a new port starts listening. The operation is protected by the
  *     vxlan_net->sock_lock.
  *
  * void (*ndo_del_vxlan_port)(struct  net_device *dev,
- *                           sa_family_t sa_family, __u16 port);
+ *                           sa_family_t sa_family, __be16 port);
  *     Called by vxlan to notify the driver about a UDP port and socket
  *     address family that vxlan is not listening to anymore. The operation
  *     is protected by the vxlan_net->sock_lock.
@@ -1093,10 +1093,10 @@ struct net_device_ops {
                                                        struct netdev_phys_port_id *ppid);
        void                    (*ndo_add_vxlan_port)(struct  net_device *dev,
                                                      sa_family_t sa_family,
-                                                     __u16 port);
+                                                     __be16 port);
        void                    (*ndo_del_vxlan_port)(struct  net_device *dev,
                                                      sa_family_t sa_family,
-                                                     __u16 port);
+                                                     __be16 port);
 };
 
 /*
index d80e2753847ce40d23e174e0b9fa623249bb4f28..9ac9fbde7b61a38795d631ab545b9bd3140fe6f6 100644 (file)
@@ -296,10 +296,12 @@ ip_set_eexist(int ret, u32 flags)
 
 /* Match elements marked with nomatch */
 static inline bool
-ip_set_enomatch(int ret, u32 flags, enum ipset_adt adt)
+ip_set_enomatch(int ret, u32 flags, enum ipset_adt adt, struct ip_set *set)
 {
        return adt == IPSET_TEST &&
-              ret == -ENOTEMPTY && ((flags >> 16) & IPSET_FLAG_NOMATCH);
+              (set->type->features & IPSET_TYPE_NOMATCH) &&
+              ((flags >> 16) & IPSET_FLAG_NOMATCH) &&
+              (ret > 0 || ret == -ENOTEMPTY);
 }
 
 /* Check the NLA_F_NET_BYTEORDER flag */
index 01fd84b566f773505122f235ceb3f70ec158bb04..49f52c8f4422ffd8ce6f0e17d33e960e92361076 100644 (file)
@@ -1455,7 +1455,8 @@ struct nfs_rpc_ops {
        struct inode * (*open_context) (struct inode *dir,
                                struct nfs_open_context *ctx,
                                int open_flags,
-                               struct iattr *iattr);
+                               struct iattr *iattr,
+                               int *);
        int (*have_delegation)(struct inode *, fmode_t);
        int (*return_delegation)(struct inode *);
        struct nfs_client *(*alloc_client) (const struct nfs_client_initdata *);
index 535cecf1e02f7823a1ec3f416c3b06382ea6d8fa..fcd63baee5f28b3361625cc1877b9a275d221204 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef __OF_IRQ_H
 #define __OF_IRQ_H
 
-#if defined(CONFIG_OF)
-struct of_irq;
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/irq.h>
@@ -10,14 +8,6 @@ struct of_irq;
 #include <linux/ioport.h>
 #include <linux/of.h>
 
-/*
- * irq_of_parse_and_map() is used by all OF enabled platforms; but SPARC
- * implements it differently.  However, the prototype is the same for all,
- * so declare it here regardless of the CONFIG_OF_IRQ setting.
- */
-extern unsigned int irq_of_parse_and_map(struct device_node *node, int index);
-
-#if defined(CONFIG_OF_IRQ)
 /**
  * of_irq - container for device_node/irq_specifier pair for an irq controller
  * @controller: pointer to interrupt controller device tree node
@@ -71,11 +61,17 @@ extern int of_irq_to_resource(struct device_node *dev, int index,
 extern int of_irq_count(struct device_node *dev);
 extern int of_irq_to_resource_table(struct device_node *dev,
                struct resource *res, int nr_irqs);
-extern struct device_node *of_irq_find_parent(struct device_node *child);
 
 extern void of_irq_init(const struct of_device_id *matches);
 
-#endif /* CONFIG_OF_IRQ */
+#if defined(CONFIG_OF)
+/*
+ * irq_of_parse_and_map() is used by all OF enabled platforms; but SPARC
+ * implements it differently.  However, the prototype is the same for all,
+ * so declare it here regardless of the CONFIG_OF_IRQ setting.
+ */
+extern unsigned int irq_of_parse_and_map(struct device_node *node, int index);
+extern struct device_node *of_irq_find_parent(struct device_node *child);
 
 #else /* !CONFIG_OF */
 static inline unsigned int irq_of_parse_and_map(struct device_node *dev,
index 67e13aa5a4781d2c8fdfa8fc902d2bbc90f2a3a0..9bdad43ad228a5501c2dc8b0e6cc77a6da8c7b30 100644 (file)
@@ -40,6 +40,8 @@ enum regulator_status {
 };
 
 /**
+ * struct regulator_linear_range - specify linear voltage ranges
+ *
  * Specify a range of voltages for regulator_map_linar_range() and
  * regulator_list_linear_range().
  *
index 2ddb48d9312c260e1e41a87ac25a19314f2aa379..c2d89335f6370d6e72a06470290a2a6e8a4cac7b 100644 (file)
@@ -498,7 +498,7 @@ struct sk_buff {
         * headers if needed
         */
        __u8                    encapsulation:1;
-       /* 7/9 bit hole (depending on ndisc_nodetype presence) */
+       /* 6/8 bit hole (depending on ndisc_nodetype presence) */
        kmemcheck_bitfield_end(flags2);
 
 #if defined CONFIG_NET_DMA || defined CONFIG_NET_RX_BUSY_POLL
index cfb7ca094b384522d2378c2a952bbe788812f1c6..731f5237d5f4e0f87dd817e15983f509d3b4d483 100644 (file)
@@ -155,6 +155,12 @@ smp_call_function_any(const struct cpumask *mask, smp_call_func_t func,
 
 static inline void kick_all_cpus_sync(void) {  }
 
+static inline void __smp_call_function_single(int cpuid,
+               struct call_single_data *data, int wait)
+{
+       on_each_cpu(data->func, data->info, wait);
+}
+
 #endif /* !SMP */
 
 /*
index b3726e61368e5c0e56bc161a41fdfce0200271b1..dd3edd7dfc94dc73de9389e55ed7f35bdcadfcbd 100644 (file)
@@ -141,6 +141,7 @@ extern int do_adjtimex(struct timex *);
 extern void hardpps(const struct timespec *, const struct timespec *);
 
 int read_current_timer(unsigned long *timer_val);
+void ntp_notify_cmos_timer(void);
 
 /* The clock frequency of the i8253/i8254 PIT */
 #define PIT_TICK_RATE 1193182ul
index 9cb2fe8ca944d5095043dd7b7ce71116a3fc21eb..e303eef94dd5cea92d16d7ae63aa35f5c3f1d4bb 100644 (file)
@@ -42,6 +42,7 @@ struct usbnet {
        struct usb_host_endpoint *status;
        unsigned                maxpacket;
        struct timer_list       delay;
+       const char              *padding_pkt;
 
        /* protocol/interface state */
        struct net_device       *net;
index fb314de2b61ba228059b1f09cb916d7d275a6a9b..86505bfa5d2c4829698d21ce81ba47575b504941 100644 (file)
@@ -67,6 +67,10 @@ int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
 int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr);
 #endif
 
+bool ipv6_chk_custom_prefix(const struct in6_addr *addr,
+                                  const unsigned int prefix_len,
+                                  struct net_device *dev);
+
 int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev);
 
 struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,
index aaeaf0938ec0af1181c4660c8fa0468937e1bc74..15f10841e2b5ddedb94dadfe166e2fe19b09cfee 100644 (file)
@@ -104,6 +104,7 @@ enum {
 enum {
        HCI_SETUP,
        HCI_AUTO_OFF,
+       HCI_RFKILLED,
        HCI_MGMT,
        HCI_PAIRABLE,
        HCI_SERVICE_CACHE,
index 48f55979d842c3e9d46eedb5c6d893374c0ef499..5e5268807a1ceb521f673ca05ec3233389a97f61 100644 (file)
@@ -264,9 +264,11 @@ int ip_dont_fragment(struct sock *sk, struct dst_entry *dst)
 
 extern void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more);
 
-static inline void ip_select_ident(struct iphdr *iph, struct dst_entry *dst, struct sock *sk)
+static inline void ip_select_ident(struct sk_buff *skb, struct dst_entry *dst, struct sock *sk)
 {
-       if (iph->frag_off & htons(IP_DF)) {
+       struct iphdr *iph = ip_hdr(skb);
+
+       if ((iph->frag_off & htons(IP_DF)) && !skb->local_df) {
                /* This is only to work around buggy Windows95/2000
                 * VJ compression implementations.  If the ID field
                 * does not change, they drop every other packet in
@@ -278,9 +280,11 @@ static inline void ip_select_ident(struct iphdr *iph, struct dst_entry *dst, str
                __ip_select_ident(iph, dst, 0);
 }
 
-static inline void ip_select_ident_more(struct iphdr *iph, struct dst_entry *dst, struct sock *sk, int more)
+static inline void ip_select_ident_more(struct sk_buff *skb, struct dst_entry *dst, struct sock *sk, int more)
 {
-       if (iph->frag_off & htons(IP_DF)) {
+       struct iphdr *iph = ip_hdr(skb);
+
+       if ((iph->frag_off & htons(IP_DF)) && !skb->local_df) {
                if (sk && inet_sk(sk)->inet_daddr) {
                        iph->id = htons(inet_sk(sk)->inet_id);
                        inet_sk(sk)->inet_id += 1 + more;
index f0d70f066f3ddc59a0c1c7bb5e58daf1c4b3c3a4..9c4d37ec45a1e5dd0536dcbef7fdfa8eac684401 100644 (file)
@@ -723,8 +723,6 @@ struct ip_vs_dest_dst {
        struct rcu_head         rcu_head;
 };
 
-/* In grace period after removing */
-#define IP_VS_DEST_STATE_REMOVING      0x01
 /*
  *     The real server destination forwarding entry
  *     with ip address, port number, and so on.
@@ -742,7 +740,7 @@ struct ip_vs_dest {
 
        atomic_t                refcnt;         /* reference counter */
        struct ip_vs_stats      stats;          /* statistics */
-       unsigned long           state;          /* state flags */
+       unsigned long           idle_start;     /* start time, jiffies */
 
        /* connection counters and thresholds */
        atomic_t                activeconns;    /* active connections */
@@ -756,14 +754,13 @@ struct ip_vs_dest {
        struct ip_vs_dest_dst __rcu *dest_dst;  /* cached dst info */
 
        /* for virtual service */
-       struct ip_vs_service    *svc;           /* service it belongs to */
+       struct ip_vs_service __rcu *svc;        /* service it belongs to */
        __u16                   protocol;       /* which protocol (TCP/UDP) */
        __be16                  vport;          /* virtual port number */
        union nf_inet_addr      vaddr;          /* virtual IP address */
        __u32                   vfwmark;        /* firewall mark of service */
 
        struct list_head        t_list;         /* in dest_trash */
-       struct rcu_head         rcu_head;
        unsigned int            in_rs_table:1;  /* we are in rs_table */
 };
 
@@ -1649,7 +1646,7 @@ static inline void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp)
 /* CONFIG_IP_VS_NFCT */
 #endif
 
-static inline unsigned int
+static inline int
 ip_vs_dest_conn_overhead(struct ip_vs_dest *dest)
 {
        /*
index 4fbf02aa2ec1e76a5c18257b0b73949e501c56a5..0f7558b638ae6ff9d0cde2b9e45e13990269005b 100644 (file)
@@ -112,6 +112,7 @@ struct mrp_applicant {
        struct mrp_application  *app;
        struct net_device       *dev;
        struct timer_list       join_timer;
+       struct timer_list       periodic_timer;
 
        spinlock_t              lock;
        struct sk_buff_head     queue;
index 1313456a0994e03cab0859e7960773b0115f8652..9d22f08896c6c16d5a1c26fad0ef65461980d02a 100644 (file)
@@ -74,6 +74,7 @@ struct net {
        struct hlist_head       *dev_index_head;
        unsigned int            dev_base_seq;   /* protected by rtnl_mutex */
        int                     ifindex;
+       unsigned int            dev_unreg_count;
 
        /* core fib_rules */
        struct list_head        rules_ops;
index ff95434e50ca4273e7e795e55f37134457cca69f..88a1d4060d5260f7ac51e7b2d74f87ab409cd4de 100644 (file)
@@ -86,7 +86,7 @@ static inline void nf_ct_ext_destroy(struct nf_conn *ct)
 static inline void nf_ct_ext_free(struct nf_conn *ct)
 {
        if (ct->ext)
-               kfree(ct->ext);
+               kfree_rcu(ct->ext, rcu);
 }
 
 /* Add this type, returns pointer to data or NULL. */
index 806f54a290d60476e0e25193d3565b611febece3..f572f313d6f1e0d7ae61f345b9aeb15a7dfea0a2 100644 (file)
@@ -56,7 +56,7 @@ struct synproxy_options {
 
 struct tcphdr;
 struct xt_synproxy_info;
-extern void synproxy_parse_options(const struct sk_buff *skb, unsigned int doff,
+extern bool synproxy_parse_options(const struct sk_buff *skb, unsigned int doff,
                                   const struct tcphdr *th,
                                   struct synproxy_options *opts);
 extern unsigned int synproxy_options_size(const struct synproxy_options *opts);
index 6ca975bebd37deea98470a75053f399671092498..c2e542b27a5a8316f3b105b2338bc96d5698690e 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <linux/types.h>
 
-extern void net_secret_init(void);
 extern __u32 secure_ip_id(__be32 daddr);
 extern __u32 secure_ipv6_id(const __be32 daddr[4]);
 extern u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
index 6ba2e7b0e2b1300f3983ef4d3c845e257d46c579..1d37a8086bed53575fedc30b9c1db750d4cd2822 100644 (file)
@@ -409,6 +409,11 @@ struct sock {
        void                    (*sk_destruct)(struct sock *sk);
 };
 
+#define __sk_user_data(sk) ((*((void __rcu **)&(sk)->sk_user_data)))
+
+#define rcu_dereference_sk_user_data(sk)       rcu_dereference(__sk_user_data((sk)))
+#define rcu_assign_sk_user_data(sk, ptr)       rcu_assign_pointer(__sk_user_data((sk)), ptr)
+
 /*
  * SK_CAN_REUSE and SK_NO_REUSE on a socket mean that the socket is OK
  * or not whether his port will be reused by someone else. SK_FORCE_REUSE
index 60ae7c3db912de7e068452de1a1c1978cad0a662..4c2301d2ef1aa979ea0d6594ad1b6404368b920b 100644 (file)
@@ -618,6 +618,7 @@ TRACE_EVENT(block_rq_remap,
                __field( unsigned int,  nr_sector       )
                __field( dev_t,         old_dev         )
                __field( sector_t,      old_sector      )
+               __field( unsigned int,  nr_bios         )
                __array( char,          rwbs,   RWBS_LEN)
        ),
 
@@ -627,15 +628,16 @@ TRACE_EVENT(block_rq_remap,
                __entry->nr_sector      = blk_rq_sectors(rq);
                __entry->old_dev        = dev;
                __entry->old_sector     = from;
+               __entry->nr_bios        = blk_rq_count_bios(rq);
                blk_fill_rwbs(__entry->rwbs, rq->cmd_flags, blk_rq_bytes(rq));
        ),
 
-       TP_printk("%d,%d %s %llu + %u <- (%d,%d) %llu",
+       TP_printk("%d,%d %s %llu + %u <- (%d,%d) %llu %u",
                  MAJOR(__entry->dev), MINOR(__entry->dev), __entry->rwbs,
                  (unsigned long long)__entry->sector,
                  __entry->nr_sector,
                  MAJOR(__entry->old_dev), MINOR(__entry->old_dev),
-                 (unsigned long long)__entry->old_sector)
+                 (unsigned long long)__entry->old_sector, __entry->nr_bios)
 );
 
 #endif /* _TRACE_BLOCK_H */
index 45702c3c3837f316709438a462d4a6517e0ba168..f18b3b76e01e22e00c00ee133b2ebdc1013bcc62 100644 (file)
@@ -42,6 +42,7 @@ struct extent_buffer;
                { BTRFS_TREE_LOG_OBJECTID,      "TREE_LOG"      },      \
                { BTRFS_QUOTA_TREE_OBJECTID,    "QUOTA_TREE"    },      \
                { BTRFS_TREE_RELOC_OBJECTID,    "TREE_RELOC"    },      \
+               { BTRFS_UUID_TREE_OBJECTID,     "UUID_RELOC"    },      \
                { BTRFS_DATA_RELOC_TREE_OBJECTID, "DATA_RELOC_TREE" })
 
 #define show_root_type(obj)                                            \
diff --git a/include/trace/events/power_cpu_migrate.h b/include/trace/events/power_cpu_migrate.h
new file mode 100644 (file)
index 0000000..f76dd4d
--- /dev/null
@@ -0,0 +1,67 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM power
+
+#if !defined(_TRACE_POWER_CPU_MIGRATE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_POWER_CPU_MIGRATE_H
+
+#include <linux/tracepoint.h>
+
+#define __cpu_migrate_proto                    \
+       TP_PROTO(u64 timestamp,                 \
+                u32 cpu_hwid)
+#define __cpu_migrate_args                     \
+       TP_ARGS(timestamp,                      \
+               cpu_hwid)
+
+DECLARE_EVENT_CLASS(cpu_migrate,
+
+       __cpu_migrate_proto,
+       __cpu_migrate_args,
+
+       TP_STRUCT__entry(
+               __field(u64,    timestamp               )
+               __field(u32,    cpu_hwid                )
+       ),
+
+       TP_fast_assign(
+               __entry->timestamp = timestamp;
+               __entry->cpu_hwid = cpu_hwid;
+       ),
+
+       TP_printk("timestamp=%llu cpu_hwid=0x%08lX",
+               (unsigned long long)__entry->timestamp,
+               (unsigned long)__entry->cpu_hwid
+       )
+);
+
+#define __define_cpu_migrate_event(name)               \
+       DEFINE_EVENT(cpu_migrate, cpu_migrate_##name,   \
+               __cpu_migrate_proto,                    \
+               __cpu_migrate_args                      \
+       )
+
+__define_cpu_migrate_event(begin);
+__define_cpu_migrate_event(finish);
+__define_cpu_migrate_event(current);
+
+#undef __define_cpu_migrate
+#undef __cpu_migrate_proto
+#undef __cpu_migrate_args
+
+/* This file can get included multiple times, TRACE_HEADER_MULTI_READ at top */
+#ifndef _PWR_CPU_MIGRATE_EVENT_AVOID_DOUBLE_DEFINING
+#define _PWR_CPU_MIGRATE_EVENT_AVOID_DOUBLE_DEFINING
+
+/*
+ * Set from_phys_cpu and to_phys_cpu to CPU_MIGRATE_ALL_CPUS to indicate
+ * a whole-cluster migration:
+ */
+#define CPU_MIGRATE_ALL_CPUS 0x80000000U
+#endif
+
+#endif /* _TRACE_POWER_CPU_MIGRATE_H */
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE power_cpu_migrate
+#include <trace/define_trace.h>
index fa8b3adf9ffbbc478a7aae0f83ffbe3bd584a91b..46d41e8b0dccec30ec5b52f6dc772bf9e3088dc6 100644 (file)
@@ -1007,4 +1007,6 @@ struct drm_radeon_info {
 #define SI_TILE_MODE_DEPTH_STENCIL_2D_4AA      3
 #define SI_TILE_MODE_DEPTH_STENCIL_2D_8AA      2
 
+#define CIK_TILE_MODE_DEPTH_STENCIL_1D         5
+
 #endif
index ca1d90bcb74d248ddb48323279bd0b3d4520d489..009a655a5d354c51e20fb34cb12ca653e94f9b71 100644 (file)
@@ -324,7 +324,7 @@ struct perf_event_attr {
 #define PERF_EVENT_IOC_PERIOD          _IOW('$', 4, __u64)
 #define PERF_EVENT_IOC_SET_OUTPUT      _IO ('$', 5)
 #define PERF_EVENT_IOC_SET_FILTER      _IOW('$', 6, char *)
-#define PERF_EVENT_IOC_ID              _IOR('$', 7, u64 *)
+#define PERF_EVENT_IOC_ID              _IOR('$', 7, __u64 *)
 
 enum perf_event_ioc_flags {
        PERF_IOC_FLAG_GROUP             = 1U << 0,
@@ -380,10 +380,13 @@ struct perf_event_mmap_page {
        union {
                __u64   capabilities;
                struct {
-                       __u64   cap_usr_time            : 1,
-                               cap_usr_rdpmc           : 1,
-                               cap_usr_time_zero       : 1,
-                               cap_____res             : 61;
+                       __u64   cap_bit0                : 1, /* Always 0, deprecated, see commit 860f085b74e9 */
+                               cap_bit0_is_deprecated  : 1, /* Always 1, signals that bit 0 is zero */
+
+                               cap_user_rdpmc          : 1, /* The RDPMC instruction can be used to read counts */
+                               cap_user_time           : 1, /* The time_* fields are used */
+                               cap_user_time_zero      : 1, /* The time_zero field is used */
+                               cap_____res             : 59;
                };
        };
 
@@ -442,12 +445,13 @@ struct perf_event_mmap_page {
         *               ((rem * time_mult) >> time_shift);
         */
        __u64   time_zero;
+       __u32   size;                   /* Header size up to __reserved[] fields. */
 
                /*
                 * Hole for extension of the self monitor capabilities
                 */
 
-       __u64   __reserved[119];        /* align to 1k */
+       __u8    __reserved[118*8+4];    /* align to 1k. */
 
        /*
         * Control data for the mmap() data buffer.
@@ -528,6 +532,7 @@ enum perf_event_type {
         *      u64                             len;
         *      u64                             pgoff;
         *      char                            filename[];
+        *      struct sample_id                sample_id;
         * };
         */
        PERF_RECORD_MMAP                        = 1,
index b0d541d426771caec217961b031e3de191135ced..558aa91186b6ced1a27b1e05b65c5ee129e0a175 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -165,6 +165,15 @@ static inline void msg_rmid(struct ipc_namespace *ns, struct msg_queue *s)
        ipc_rmid(&msg_ids(ns), &s->q_perm);
 }
 
+static void msg_rcu_free(struct rcu_head *head)
+{
+       struct ipc_rcu *p = container_of(head, struct ipc_rcu, rcu);
+       struct msg_queue *msq = ipc_rcu_to_struct(p);
+
+       security_msg_queue_free(msq);
+       ipc_rcu_free(head);
+}
+
 /**
  * newque - Create a new msg queue
  * @ns: namespace
@@ -189,15 +198,14 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
        msq->q_perm.security = NULL;
        retval = security_msg_queue_alloc(msq);
        if (retval) {
-               ipc_rcu_putref(msq);
+               ipc_rcu_putref(msq, ipc_rcu_free);
                return retval;
        }
 
        /* ipc_addid() locks msq upon success. */
        id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni);
        if (id < 0) {
-               security_msg_queue_free(msq);
-               ipc_rcu_putref(msq);
+               ipc_rcu_putref(msq, msg_rcu_free);
                return id;
        }
 
@@ -276,8 +284,7 @@ static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
                free_msg(msg);
        }
        atomic_sub(msq->q_cbytes, &ns->msg_bytes);
-       security_msg_queue_free(msq);
-       ipc_rcu_putref(msq);
+       ipc_rcu_putref(msq, msg_rcu_free);
 }
 
 /*
@@ -688,6 +695,12 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
                if (ipcperms(ns, &msq->q_perm, S_IWUGO))
                        goto out_unlock0;
 
+               /* raced with RMID? */
+               if (msq->q_perm.deleted) {
+                       err = -EIDRM;
+                       goto out_unlock0;
+               }
+
                err = security_msg_queue_msgsnd(msq, msg, msgflg);
                if (err)
                        goto out_unlock0;
@@ -717,7 +730,7 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
                rcu_read_lock();
                ipc_lock_object(&msq->q_perm);
 
-               ipc_rcu_putref(msq);
+               ipc_rcu_putref(msq, ipc_rcu_free);
                if (msq->q_perm.deleted) {
                        err = -EIDRM;
                        goto out_unlock0;
@@ -894,6 +907,13 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgfl
                        goto out_unlock1;
 
                ipc_lock_object(&msq->q_perm);
+
+               /* raced with RMID? */
+               if (msq->q_perm.deleted) {
+                       msg = ERR_PTR(-EIDRM);
+                       goto out_unlock0;
+               }
+
                msg = find_msg(msq, &msgtyp, mode);
                if (!IS_ERR(msg)) {
                        /*
index 69b6a21f38441aa437a8f79cb53ae4c4a6a520a1..8c4f59b0204a2821811a4b28fd48e0ce6163d987 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -243,71 +243,122 @@ static void merge_queues(struct sem_array *sma)
        }
 }
 
+static void sem_rcu_free(struct rcu_head *head)
+{
+       struct ipc_rcu *p = container_of(head, struct ipc_rcu, rcu);
+       struct sem_array *sma = ipc_rcu_to_struct(p);
+
+       security_sem_free(sma);
+       ipc_rcu_free(head);
+}
+
+/*
+ * Wait until all currently ongoing simple ops have completed.
+ * Caller must own sem_perm.lock.
+ * New simple ops cannot start, because simple ops first check
+ * that sem_perm.lock is free.
+ * that a) sem_perm.lock is free and b) complex_count is 0.
+ */
+static void sem_wait_array(struct sem_array *sma)
+{
+       int i;
+       struct sem *sem;
+
+       if (sma->complex_count)  {
+               /* The thread that increased sma->complex_count waited on
+                * all sem->lock locks. Thus we don't need to wait again.
+                */
+               return;
+       }
+
+       for (i = 0; i < sma->sem_nsems; i++) {
+               sem = sma->sem_base + i;
+               spin_unlock_wait(&sem->lock);
+       }
+}
+
 /*
  * If the request contains only one semaphore operation, and there are
  * no complex transactions pending, lock only the semaphore involved.
  * Otherwise, lock the entire semaphore array, since we either have
  * multiple semaphores in our own semops, or we need to look at
  * semaphores from other pending complex operations.
- *
- * Carefully guard against sma->complex_count changing between zero
- * and non-zero while we are spinning for the lock. The value of
- * sma->complex_count cannot change while we are holding the lock,
- * so sem_unlock should be fine.
- *
- * The global lock path checks that all the local locks have been released,
- * checking each local lock once. This means that the local lock paths
- * cannot start their critical sections while the global lock is held.
  */
 static inline int sem_lock(struct sem_array *sma, struct sembuf *sops,
                              int nsops)
 {
-       int locknum;
- again:
-       if (nsops == 1 && !sma->complex_count) {
-               struct sem *sem = sma->sem_base + sops->sem_num;
+       struct sem *sem;
 
-               /* Lock just the semaphore we are interested in. */
-               spin_lock(&sem->lock);
+       if (nsops != 1) {
+               /* Complex operation - acquire a full lock */
+               ipc_lock_object(&sma->sem_perm);
 
-               /*
-                * If sma->complex_count was set while we were spinning,
-                * we may need to look at things we did not lock here.
+               /* And wait until all simple ops that are processed
+                * right now have dropped their locks.
                 */
-               if (unlikely(sma->complex_count)) {
-                       spin_unlock(&sem->lock);
-                       goto lock_array;
-               }
+               sem_wait_array(sma);
+               return -1;
+       }
+
+       /*
+        * Only one semaphore affected - try to optimize locking.
+        * The rules are:
+        * - optimized locking is possible if no complex operation
+        *   is either enqueued or processed right now.
+        * - The test for enqueued complex ops is simple:
+        *      sma->complex_count != 0
+        * - Testing for complex ops that are processed right now is
+        *   a bit more difficult. Complex ops acquire the full lock
+        *   and first wait that the running simple ops have completed.
+        *   (see above)
+        *   Thus: If we own a simple lock and the global lock is free
+        *      and complex_count is now 0, then it will stay 0 and
+        *      thus just locking sem->lock is sufficient.
+        */
+       sem = sma->sem_base + sops->sem_num;
 
+       if (sma->complex_count == 0) {
                /*
-                * Another process is holding the global lock on the
-                * sem_array; we cannot enter our critical section,
-                * but have to wait for the global lock to be released.
+                * It appears that no complex operation is around.
+                * Acquire the per-semaphore lock.
                 */
-               if (unlikely(spin_is_locked(&sma->sem_perm.lock))) {
-                       spin_unlock(&sem->lock);
-                       spin_unlock_wait(&sma->sem_perm.lock);
-                       goto again;
+               spin_lock(&sem->lock);
+
+               /* Then check that the global lock is free */
+               if (!spin_is_locked(&sma->sem_perm.lock)) {
+                       /* spin_is_locked() is not a memory barrier */
+                       smp_mb();
+
+                       /* Now repeat the test of complex_count:
+                        * It can't change anymore until we drop sem->lock.
+                        * Thus: if is now 0, then it will stay 0.
+                        */
+                       if (sma->complex_count == 0) {
+                               /* fast path successful! */
+                               return sops->sem_num;
+                       }
                }
+               spin_unlock(&sem->lock);
+       }
 
-               locknum = sops->sem_num;
+       /* slow path: acquire the full lock */
+       ipc_lock_object(&sma->sem_perm);
+
+       if (sma->complex_count == 0) {
+               /* False alarm:
+                * There is no complex operation, thus we can switch
+                * back to the fast path.
+                */
+               spin_lock(&sem->lock);
+               ipc_unlock_object(&sma->sem_perm);
+               return sops->sem_num;
        } else {
-               int i;
-               /*
-                * Lock the semaphore array, and wait for all of the
-                * individual semaphore locks to go away.  The code
-                * above ensures no new single-lock holders will enter
-                * their critical section while the array lock is held.
+               /* Not a false alarm, thus complete the sequence for a
+                * full lock.
                 */
- lock_array:
-               ipc_lock_object(&sma->sem_perm);
-               for (i = 0; i < sma->sem_nsems; i++) {
-                       struct sem *sem = sma->sem_base + i;
-                       spin_unlock_wait(&sem->lock);
-               }
-               locknum = -1;
+               sem_wait_array(sma);
+               return -1;
        }
-       return locknum;
 }
 
 static inline void sem_unlock(struct sem_array *sma, int locknum)
@@ -374,12 +425,7 @@ static inline struct sem_array *sem_obtain_object_check(struct ipc_namespace *ns
 static inline void sem_lock_and_putref(struct sem_array *sma)
 {
        sem_lock(sma, NULL, -1);
-       ipc_rcu_putref(sma);
-}
-
-static inline void sem_putref(struct sem_array *sma)
-{
-       ipc_rcu_putref(sma);
+       ipc_rcu_putref(sma, ipc_rcu_free);
 }
 
 static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
@@ -458,14 +504,13 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
        sma->sem_perm.security = NULL;
        retval = security_sem_alloc(sma);
        if (retval) {
-               ipc_rcu_putref(sma);
+               ipc_rcu_putref(sma, ipc_rcu_free);
                return retval;
        }
 
        id = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni);
        if (id < 0) {
-               security_sem_free(sma);
-               ipc_rcu_putref(sma);
+               ipc_rcu_putref(sma, sem_rcu_free);
                return id;
        }
        ns->used_sems += nsems;
@@ -872,6 +917,24 @@ again:
        return semop_completed;
 }
 
+/**
+ * set_semotime(sma, sops) - set sem_otime
+ * @sma: semaphore array
+ * @sops: operations that modified the array, may be NULL
+ *
+ * sem_otime is replicated to avoid cache line trashing.
+ * This function sets one instance to the current time.
+ */
+static void set_semotime(struct sem_array *sma, struct sembuf *sops)
+{
+       if (sops == NULL) {
+               sma->sem_base[0].sem_otime = get_seconds();
+       } else {
+               sma->sem_base[sops[0].sem_num].sem_otime =
+                                                       get_seconds();
+       }
+}
+
 /**
  * do_smart_update(sma, sops, nsops, otime, pt) - optimized update_queue
  * @sma: semaphore array
@@ -922,17 +985,10 @@ static void do_smart_update(struct sem_array *sma, struct sembuf *sops, int nsop
                        }
                }
        }
-       if (otime) {
-               if (sops == NULL) {
-                       sma->sem_base[0].sem_otime = get_seconds();
-               } else {
-                       sma->sem_base[sops[0].sem_num].sem_otime =
-                                                               get_seconds();
-               }
-       }
+       if (otime)
+               set_semotime(sma, sops);
 }
 
-
 /* The following counts are associated to each semaphore:
  *   semncnt        number of tasks waiting on semval being nonzero
  *   semzcnt        number of tasks waiting on semval being zero
@@ -1047,8 +1103,7 @@ static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
 
        wake_up_sem_queue_do(&tasks);
        ns->used_sems -= sma->sem_nsems;
-       security_sem_free(sma);
-       ipc_rcu_putref(sma);
+       ipc_rcu_putref(sma, sem_rcu_free);
 }
 
 static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in, int version)
@@ -1292,7 +1347,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                        rcu_read_unlock();
                        sem_io = ipc_alloc(sizeof(ushort)*nsems);
                        if(sem_io == NULL) {
-                               sem_putref(sma);
+                               ipc_rcu_putref(sma, ipc_rcu_free);
                                return -ENOMEM;
                        }
 
@@ -1328,20 +1383,20 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                if(nsems > SEMMSL_FAST) {
                        sem_io = ipc_alloc(sizeof(ushort)*nsems);
                        if(sem_io == NULL) {
-                               sem_putref(sma);
+                               ipc_rcu_putref(sma, ipc_rcu_free);
                                return -ENOMEM;
                        }
                }
 
                if (copy_from_user (sem_io, p, nsems*sizeof(ushort))) {
-                       sem_putref(sma);
+                       ipc_rcu_putref(sma, ipc_rcu_free);
                        err = -EFAULT;
                        goto out_free;
                }
 
                for (i = 0; i < nsems; i++) {
                        if (sem_io[i] > SEMVMX) {
-                               sem_putref(sma);
+                               ipc_rcu_putref(sma, ipc_rcu_free);
                                err = -ERANGE;
                                goto out_free;
                        }
@@ -1629,7 +1684,7 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
        /* step 2: allocate new undo structure */
        new = kzalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL);
        if (!new) {
-               sem_putref(sma);
+               ipc_rcu_putref(sma, ipc_rcu_free);
                return ERR_PTR(-ENOMEM);
        }
 
@@ -1795,12 +1850,17 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 
        error = perform_atomic_semop(sma, sops, nsops, un,
                                        task_tgid_vnr(current));
-       if (error <= 0) {
-               if (alter && error == 0)
+       if (error == 0) {
+               /* If the operation was successful, then do
+                * the required updates.
+                */
+               if (alter)
                        do_smart_update(sma, sops, nsops, 1, &tasks);
-
-               goto out_unlock_free;
+               else
+                       set_semotime(sma, sops);
        }
+       if (error <= 0)
+               goto out_unlock_free;
 
        /* We need to sleep on this operation, so we put the current
         * task into the pending queue and go to sleep.
@@ -2059,6 +2119,14 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it)
        struct sem_array *sma = it;
        time_t sem_otime;
 
+       /*
+        * The proc interface isn't aware of sem_lock(), it calls
+        * ipc_lock_object() directly (in sysvipc_find_ipc).
+        * In order to stay compatible with sem_lock(), we must wait until
+        * all simple semop() calls have left their critical regions.
+        */
+       sem_wait_array(sma);
+
        sem_otime = get_semotime(sma);
 
        return seq_printf(s,
index 2821cdf93adb39ac83f8a604e6f487590bfe01f7..d69739610fd4384323004c46782116d54db6bbd5 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -167,6 +167,15 @@ static inline void shm_lock_by_ptr(struct shmid_kernel *ipcp)
        ipc_lock_object(&ipcp->shm_perm);
 }
 
+static void shm_rcu_free(struct rcu_head *head)
+{
+       struct ipc_rcu *p = container_of(head, struct ipc_rcu, rcu);
+       struct shmid_kernel *shp = ipc_rcu_to_struct(p);
+
+       security_shm_free(shp);
+       ipc_rcu_free(head);
+}
+
 static inline void shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *s)
 {
        ipc_rmid(&shm_ids(ns), &s->shm_perm);
@@ -208,8 +217,7 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
                user_shm_unlock(file_inode(shp->shm_file)->i_size,
                                                shp->mlock_user);
        fput (shp->shm_file);
-       security_shm_free(shp);
-       ipc_rcu_putref(shp);
+       ipc_rcu_putref(shp, shm_rcu_free);
 }
 
 /*
@@ -497,7 +505,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
        shp->shm_perm.security = NULL;
        error = security_shm_alloc(shp);
        if (error) {
-               ipc_rcu_putref(shp);
+               ipc_rcu_putref(shp, ipc_rcu_free);
                return error;
        }
 
@@ -566,8 +574,7 @@ no_id:
                user_shm_unlock(size, shp->mlock_user);
        fput(file);
 no_file:
-       security_shm_free(shp);
-       ipc_rcu_putref(shp);
+       ipc_rcu_putref(shp, shm_rcu_free);
        return error;
 }
 
index e829da9ed01f3dbe2973fd232a4f2b889f401c9c..fdb8ae7407755f9b1c3725e2a7fd38a8a31c7f54 100644 (file)
@@ -474,11 +474,6 @@ void ipc_free(void* ptr, int size)
                kfree(ptr);
 }
 
-struct ipc_rcu {
-       struct rcu_head rcu;
-       atomic_t refcount;
-} ____cacheline_aligned_in_smp;
-
 /**
  *     ipc_rcu_alloc   -       allocate ipc and rcu space 
  *     @size: size desired
@@ -505,27 +500,24 @@ int ipc_rcu_getref(void *ptr)
        return atomic_inc_not_zero(&p->refcount);
 }
 
-/**
- * ipc_schedule_free - free ipc + rcu space
- * @head: RCU callback structure for queued work
- */
-static void ipc_schedule_free(struct rcu_head *head)
-{
-       vfree(container_of(head, struct ipc_rcu, rcu));
-}
-
-void ipc_rcu_putref(void *ptr)
+void ipc_rcu_putref(void *ptr, void (*func)(struct rcu_head *head))
 {
        struct ipc_rcu *p = ((struct ipc_rcu *)ptr) - 1;
 
        if (!atomic_dec_and_test(&p->refcount))
                return;
 
-       if (is_vmalloc_addr(ptr)) {
-               call_rcu(&p->rcu, ipc_schedule_free);
-       } else {
-               kfree_rcu(p, rcu);
-       }
+       call_rcu(&p->rcu, func);
+}
+
+void ipc_rcu_free(struct rcu_head *head)
+{
+       struct ipc_rcu *p = container_of(head, struct ipc_rcu, rcu);
+
+       if (is_vmalloc_addr(p))
+               vfree(p);
+       else
+               kfree(p);
 }
 
 /**
index c5f3338ba1fa7913967c1bc7e9845e0561eeb027..f2f5036f2eeda9794bc545ac8045db3c56f7d425 100644 (file)
@@ -47,6 +47,13 @@ static inline void msg_exit_ns(struct ipc_namespace *ns) { }
 static inline void shm_exit_ns(struct ipc_namespace *ns) { }
 #endif
 
+struct ipc_rcu {
+       struct rcu_head rcu;
+       atomic_t refcount;
+} ____cacheline_aligned_in_smp;
+
+#define ipc_rcu_to_struct(p)  ((void *)(p+1))
+
 /*
  * Structure that holds the parameters needed by the ipc operations
  * (see after)
@@ -120,7 +127,8 @@ void ipc_free(void* ptr, int size);
  */
 void* ipc_rcu_alloc(int size);
 int ipc_rcu_getref(void *ptr);
-void ipc_rcu_putref(void *ptr);
+void ipc_rcu_putref(void *ptr, void (*func)(struct rcu_head *head));
+void ipc_rcu_free(struct rcu_head *head);
 
 struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int);
 struct kern_ipc_perm *ipc_obtain_object(struct ipc_ids *ids, int id);
index 91e53d04b6a9e8841e697dcb290f1206468da21a..7b0e23a740ce345987c33f9e012302c24de0f4db 100644 (file)
@@ -1117,9 +1117,10 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
 
                        sleep_time = timeout_start + audit_backlog_wait_time -
                                        jiffies;
-                       if ((long)sleep_time > 0)
+                       if ((long)sleep_time > 0) {
                                wait_for_auditd(sleep_time);
-                       continue;
+                               continue;
+                       }
                }
                if (audit_rate_check() && printk_ratelimit())
                        printk(KERN_WARNING
index 247091bf0587a479594776be800db9164a10ae8b..859c8dfd78a1a5b296dd5c6c23d741e7a4c1e8cd 100644 (file)
@@ -50,6 +50,15 @@ void context_tracking_user_enter(void)
 {
        unsigned long flags;
 
+       /*
+        * Repeat the user_enter() check here because some archs may be calling
+        * this from asm and if no CPU needs context tracking, they shouldn't
+        * go further. Repeat the check here until they support the static key
+        * check.
+        */
+       if (!static_key_false(&context_tracking_enabled))
+               return;
+
        /*
         * Some contexts may involve an exception occuring in an irq,
         * leading to that nesting:
@@ -151,6 +160,9 @@ void context_tracking_user_exit(void)
 {
        unsigned long flags;
 
+       if (!static_key_false(&context_tracking_enabled))
+               return;
+
        if (in_interrupt())
                return;
 
index dd236b66ca3a8ef894386e7dcb8c7f02dbba34ae..cb4238e85b38e37886b27dd76351d2590a835924 100644 (file)
@@ -3660,6 +3660,26 @@ static void calc_timer_values(struct perf_event *event,
        *running = ctx_time - event->tstamp_running;
 }
 
+static void perf_event_init_userpage(struct perf_event *event)
+{
+       struct perf_event_mmap_page *userpg;
+       struct ring_buffer *rb;
+
+       rcu_read_lock();
+       rb = rcu_dereference(event->rb);
+       if (!rb)
+               goto unlock;
+
+       userpg = rb->user_page;
+
+       /* Allow new userspace to detect that bit 0 is deprecated */
+       userpg->cap_bit0_is_deprecated = 1;
+       userpg->size = offsetof(struct perf_event_mmap_page, __reserved);
+
+unlock:
+       rcu_read_unlock();
+}
+
 void __weak arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now)
 {
 }
@@ -4044,6 +4064,7 @@ again:
        ring_buffer_attach(event, rb);
        rcu_assign_pointer(event->rb, rb);
 
+       perf_event_init_userpage(event);
        perf_event_update_userpage(event);
 
 unlock:
index fb326365b69466158b03b726e53c4fe15448fa89..b086006c59e7c6957a51984a3ec101ea2db8525d 100644 (file)
@@ -571,6 +571,10 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait)
        DECLARE_COMPLETION_ONSTACK(done);
        int retval = 0;
 
+       if (!sub_info->path) {
+               call_usermodehelper_freeinfo(sub_info);
+               return -EINVAL;
+       }
        helper_lock();
        if (!khelper_wq || usermodehelper_disabled) {
                retval = -EBUSY;
index 81c4e78c8f4cc0b79b89086c3255934079082380..c00d5b502aa487de0f09117c21dfa12eb8923e0c 100644 (file)
@@ -254,11 +254,11 @@ int parse_args(const char *doing,
 
 
 STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", unsigned long, kstrtoul);
-STANDARD_PARAM_DEF(short, short, "%hi", long, kstrtoul);
+STANDARD_PARAM_DEF(short, short, "%hi", long, kstrtol);
 STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, kstrtoul);
-STANDARD_PARAM_DEF(int, int, "%i", long, kstrtoul);
+STANDARD_PARAM_DEF(int, int, "%i", long, kstrtol);
 STANDARD_PARAM_DEF(uint, unsigned int, "%u", unsigned long, kstrtoul);
-STANDARD_PARAM_DEF(long, long, "%li", long, kstrtoul);
+STANDARD_PARAM_DEF(long, long, "%li", long, kstrtol);
 STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, kstrtoul);
 
 int param_set_charp(const char *val, const struct kernel_param *kp)
index ebe5e80b10f8495a3d6459e0203821f987237df0..9b9a26698144e126486e162955e49561514b1ce8 100644 (file)
@@ -273,6 +273,11 @@ void free_pid(struct pid *pid)
                         */
                        wake_up_process(ns->child_reaper);
                        break;
+               case PIDNS_HASH_ADDING:
+                       /* Handle a fork failure of the first process */
+                       WARN_ON(ns->child_reaper);
+                       ns->nr_hashed = 0;
+                       /* fall through */
                case 0:
                        schedule_work(&ns->proc_work);
                        break;
index 358a146fd4dacda5462f5ef29a8f797c91868c71..98c3b34a4cffcedeae812de0ddc947f874cef839 100644 (file)
@@ -743,7 +743,10 @@ int create_basic_memory_bitmaps(void)
        struct memory_bitmap *bm1, *bm2;
        int error = 0;
 
-       BUG_ON(forbidden_pages_map || free_pages_map);
+       if (forbidden_pages_map && free_pages_map)
+               return 0;
+       else
+               BUG_ON(forbidden_pages_map || free_pages_map);
 
        bm1 = kzalloc(sizeof(struct memory_bitmap), GFP_KERNEL);
        if (!bm1)
index 72e8f4fd616dee0cec880d442e33127602601f6c..957f06164ad1004b0050dbdcb7563c91c3755e55 100644 (file)
@@ -39,6 +39,7 @@ static struct snapshot_data {
        char frozen;
        char ready;
        char platform_support;
+       bool free_bitmaps;
 } snapshot_state;
 
 atomic_t snapshot_device_available = ATOMIC_INIT(1);
@@ -82,6 +83,10 @@ static int snapshot_open(struct inode *inode, struct file *filp)
                data->swap = -1;
                data->mode = O_WRONLY;
                error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
+               if (!error) {
+                       error = create_basic_memory_bitmaps();
+                       data->free_bitmaps = !error;
+               }
                if (error)
                        pm_notifier_call_chain(PM_POST_RESTORE);
        }
@@ -111,6 +116,8 @@ static int snapshot_release(struct inode *inode, struct file *filp)
                pm_restore_gfp_mask();
                free_basic_memory_bitmaps();
                thaw_processes();
+       } else if (data->free_bitmaps) {
+               free_basic_memory_bitmaps();
        }
        pm_notifier_call_chain(data->mode == O_RDONLY ?
                        PM_POST_HIBERNATION : PM_POST_RESTORE);
@@ -231,6 +238,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
                        break;
                pm_restore_gfp_mask();
                free_basic_memory_bitmaps();
+               data->free_bitmaps = false;
                thaw_processes();
                data->frozen = 0;
                break;
index 269ed9384cc4284e9cf6043bd00667ea582c4369..f813b3474646c5b320a19d9a8997349bdd14d68e 100644 (file)
@@ -32,7 +32,14 @@ EXPORT_SYMBOL(cad_pid);
 #endif
 enum reboot_mode reboot_mode DEFAULT_REBOOT_MODE;
 
-int reboot_default;
+/*
+ * This variable is used privately to keep track of whether or not
+ * reboot_type is still set to its default value (i.e., reboot= hasn't
+ * been set on the command line).  This is needed so that we can
+ * suppress DMI scanning for reboot quirks.  Without it, it's
+ * impossible to override a faulty reboot quirk without recompiling.
+ */
+int reboot_default = 1;
 int reboot_cpu;
 enum reboot_type reboot_type = BOOT_ACPI;
 int reboot_force;
index e076bddd4c66f4a007db513954c3f41240525fe2..196559994f7ce33e210f3a290043ed5862950ec6 100644 (file)
@@ -124,7 +124,7 @@ print_task(struct seq_file *m, struct rq *rq, struct task_struct *p)
                SEQ_printf(m, " ");
 
        SEQ_printf(m, "%15s %5d %9Ld.%06ld %9Ld %5d ",
-               p->comm, p->pid,
+               p->comm, task_pid_nr(p),
                SPLIT_NS(p->se.vruntime),
                (long long)(p->nvcsw + p->nivcsw),
                p->prio);
@@ -289,7 +289,7 @@ do {                                                                        \
        P(nr_load_updates);
        P(nr_uninterruptible);
        PN(next_balance);
-       P(curr->pid);
+       SEQ_printf(m, "  .%-30s: %ld\n", "curr->pid", (long)(task_pid_nr(rq->curr)));
        PN(clock);
        P(cpu_load[0]);
        P(cpu_load[1]);
@@ -492,7 +492,7 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m)
 {
        unsigned long nr_switches;
 
-       SEQ_printf(m, "%s (%d, #threads: %d)\n", p->comm, p->pid,
+       SEQ_printf(m, "%s (%d, #threads: %d)\n", p->comm, task_pid_nr(p),
                                                get_nr_threads(p));
        SEQ_printf(m,
                "---------------------------------------------------------"
index 9b3fe1cd8f40c90a67381be209db1a49dad6f6f7..7c70201fbc61aef012d5b2536600d898602bab0a 100644 (file)
@@ -4242,7 +4242,7 @@ static void update_cfs_rq_h_load(struct cfs_rq *cfs_rq)
        }
 
        if (!se) {
-               cfs_rq->h_load = rq->avg.load_avg_contrib;
+               cfs_rq->h_load = cfs_rq->runnable_load_avg;
                cfs_rq->last_h_load_update = now;
        }
 
@@ -4823,8 +4823,8 @@ void fix_small_imbalance(struct lb_env *env, struct sd_lb_stats *sds)
                (busiest->load_per_task * SCHED_POWER_SCALE) /
                busiest->group_power;
 
-       if (busiest->avg_load - local->avg_load + scaled_busy_load_per_task >=
-           (scaled_busy_load_per_task * imbn)) {
+       if (busiest->avg_load + scaled_busy_load_per_task >=
+           local->avg_load + (scaled_busy_load_per_task * imbn)) {
                env->imbalance = busiest->load_per_task;
                return;
        }
@@ -4896,7 +4896,8 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s
         * max load less than avg load(as we skip the groups at or below
         * its cpu_power, while calculating max_load..)
         */
-       if (busiest->avg_load < sds->avg_load) {
+       if (busiest->avg_load <= sds->avg_load ||
+           local->avg_load >= sds->avg_load) {
                env->imbalance = 0;
                return fix_small_imbalance(env, sds);
        }
@@ -5928,11 +5929,15 @@ static void task_fork_fair(struct task_struct *p)
        cfs_rq = task_cfs_rq(current);
        curr = cfs_rq->curr;
 
-       if (unlikely(task_cpu(p) != this_cpu)) {
-               rcu_read_lock();
-               __set_task_cpu(p, this_cpu);
-               rcu_read_unlock();
-       }
+       /*
+        * Not only the cpu but also the task_group of the parent might have
+        * been changed after parent->se.parent,cfs_rq were copied to
+        * child->se.parent,cfs_rq. So call __set_task_cpu() to make those
+        * of child point to valid ones.
+        */
+       rcu_read_lock();
+       __set_task_cpu(p, this_cpu);
+       rcu_read_unlock();
 
        update_curr(cfs_rq);
 
index 5aef494fc8b42471006a48c516737b93aa086fb7..c7edee71bce8915f67a3b4427b7f305696834afb 100644 (file)
@@ -104,8 +104,9 @@ static inline void sched_info_queued(struct task_struct *t)
 }
 
 /*
- * Called when a process ceases being the active-running process, either
- * voluntarily or involuntarily.  Now we can calculate how long we ran.
+ * Called when a process ceases being the active-running process involuntarily
+ * due, typically, to expiring its time slice (this may also be called when
+ * switching to the idle task).  Now we can calculate how long we ran.
  * Also, if the process is still in the TASK_RUNNING state, call
  * sched_info_queued() to mark that it has now again started waiting on
  * the runqueue.
index 53cc09ceb0b869cf407fdc9d8195f265cce4c011..d7d498d8cc4f8185954a220c66071cbc5761b917 100644 (file)
@@ -328,10 +328,19 @@ void irq_enter(void)
 
 static inline void invoke_softirq(void)
 {
-       if (!force_irqthreads)
-               __do_softirq();
-       else
+       if (!force_irqthreads) {
+               /*
+                * We can safely execute softirq on the current stack if
+                * it is the irq stack, because it should be near empty
+                * at this stage. But we have no way to know if the arch
+                * calls irq_exit() on the irq stack. So call softirq
+                * in its own stack to prevent from any overrun on top
+                * of a potentially deep task stack.
+                */
+               do_softirq();
+       } else {
                wakeup_softirqd();
+       }
 }
 
 static inline void tick_irq_exit(void)
index 8f5b3b98577b797663f8057762b6248d0fae1823..bb2215174f0577332cc8924eacb440703d1414d0 100644 (file)
@@ -516,13 +516,13 @@ static void sync_cmos_clock(struct work_struct *work)
        schedule_delayed_work(&sync_cmos_work, timespec_to_jiffies(&next));
 }
 
-static void notify_cmos_timer(void)
+void ntp_notify_cmos_timer(void)
 {
        schedule_delayed_work(&sync_cmos_work, 0);
 }
 
 #else
-static inline void notify_cmos_timer(void) { }
+void ntp_notify_cmos_timer(void) { }
 #endif
 
 
@@ -687,8 +687,6 @@ int __do_adjtimex(struct timex *txc, struct timespec *ts, s32 *time_tai)
        if (!(time_status & STA_NANO))
                txc->time.tv_usec /= NSEC_PER_USEC;
 
-       notify_cmos_timer();
-
        return result;
 }
 
index 48b9fffabdc294a4bea16b9b78083a161e8eec42..947ba25a95a0aeb51415591ab8e19fb1a846b989 100644 (file)
@@ -1703,6 +1703,8 @@ int do_adjtimex(struct timex *txc)
        write_seqcount_end(&timekeeper_seq);
        raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
 
+       ntp_notify_cmos_timer();
+
        return ret;
 }
 
index 51c4f34d258ea397266e0dd1a96a16436415a38f..4431610f049ac77888adefe3a335d47d4d232939 100644 (file)
@@ -486,7 +486,52 @@ static struct smp_hotplug_thread watchdog_threads = {
        .unpark                 = watchdog_enable,
 };
 
-static int watchdog_enable_all_cpus(void)
+static void restart_watchdog_hrtimer(void *info)
+{
+       struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer);
+       int ret;
+
+       /*
+        * No need to cancel and restart hrtimer if it is currently executing
+        * because it will reprogram itself with the new period now.
+        * We should never see it unqueued here because we are running per-cpu
+        * with interrupts disabled.
+        */
+       ret = hrtimer_try_to_cancel(hrtimer);
+       if (ret == 1)
+               hrtimer_start(hrtimer, ns_to_ktime(sample_period),
+                               HRTIMER_MODE_REL_PINNED);
+}
+
+static void update_timers(int cpu)
+{
+       struct call_single_data data = {.func = restart_watchdog_hrtimer};
+       /*
+        * Make sure that perf event counter will adopt to a new
+        * sampling period. Updating the sampling period directly would
+        * be much nicer but we do not have an API for that now so
+        * let's use a big hammer.
+        * Hrtimer will adopt the new period on the next tick but this
+        * might be late already so we have to restart the timer as well.
+        */
+       watchdog_nmi_disable(cpu);
+       __smp_call_function_single(cpu, &data, 1);
+       watchdog_nmi_enable(cpu);
+}
+
+static void update_timers_all_cpus(void)
+{
+       int cpu;
+
+       get_online_cpus();
+       preempt_disable();
+       for_each_online_cpu(cpu)
+               update_timers(cpu);
+       preempt_enable();
+       put_online_cpus();
+}
+
+static int watchdog_enable_all_cpus(bool sample_period_changed)
 {
        int err = 0;
 
@@ -496,6 +541,8 @@ static int watchdog_enable_all_cpus(void)
                        pr_err("Failed to create watchdog threads, disabled\n");
                else
                        watchdog_running = 1;
+       } else if (sample_period_changed) {
+               update_timers_all_cpus();
        }
 
        return err;
@@ -520,13 +567,15 @@ int proc_dowatchdog(struct ctl_table *table, int write,
                    void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        int err, old_thresh, old_enabled;
+       static DEFINE_MUTEX(watchdog_proc_mutex);
 
+       mutex_lock(&watchdog_proc_mutex);
        old_thresh = ACCESS_ONCE(watchdog_thresh);
        old_enabled = ACCESS_ONCE(watchdog_user_enabled);
 
        err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
        if (err || !write)
-               return err;
+               goto out;
 
        set_sample_period();
        /*
@@ -535,7 +584,7 @@ int proc_dowatchdog(struct ctl_table *table, int write,
         * watchdog_*_all_cpus() function takes care of this.
         */
        if (watchdog_user_enabled && watchdog_thresh)
-               err = watchdog_enable_all_cpus();
+               err = watchdog_enable_all_cpus(old_thresh != watchdog_thresh);
        else
                watchdog_disable_all_cpus();
 
@@ -544,7 +593,8 @@ int proc_dowatchdog(struct ctl_table *table, int write,
                watchdog_thresh = old_thresh;
                watchdog_user_enabled = old_enabled;
        }
-
+out:
+       mutex_unlock(&watchdog_proc_mutex);
        return err;
 }
 #endif /* CONFIG_SYSCTL */
@@ -554,5 +604,5 @@ void __init lockup_detector_init(void)
        set_sample_period();
 
        if (watchdog_user_enabled)
-               watchdog_enable_all_cpus();
+               watchdog_enable_all_cpus(false);
 }
index 3f0494c9d57aaf24cbbea90231e010d1d06f3e04..8499c810909a58ae100b7db96a01ea74b5c14948 100644 (file)
@@ -14,6 +14,8 @@
 
 const char hex_asc[] = "0123456789abcdef";
 EXPORT_SYMBOL(hex_asc);
+const char hex_asc_upper[] = "0123456789ABCDEF";
+EXPORT_SYMBOL(hex_asc_upper);
 
 /**
  * hex_to_bin - convert a hex digit to its real value
index 962175134702dace0078edfd0ec7f092bc646536..669bf190d4fb91770f8912277278a6528c4065c3 100644 (file)
@@ -933,10 +933,7 @@ const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj)
 
 bool kobj_ns_current_may_mount(enum kobj_ns_type type)
 {
-       bool may_mount = false;
-
-       if (type == KOBJ_NS_TYPE_NONE)
-               return true;
+       bool may_mount = true;
 
        spin_lock(&kobj_ns_type_lock);
        if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) &&
index e2cd2c0a882126c58e04e47102fb4975c5247d3c..6f9d434c1521eab9ca0b2821d10936af55f2b703 100644 (file)
@@ -3,6 +3,22 @@
 
 #ifdef CONFIG_CMPXCHG_LOCKREF
 
+/*
+ * Allow weakly-ordered memory architectures to provide barrier-less
+ * cmpxchg semantics for lockref updates.
+ */
+#ifndef cmpxchg64_relaxed
+# define cmpxchg64_relaxed cmpxchg64
+#endif
+
+/*
+ * Allow architectures to override the default cpu_relax() within CMPXCHG_LOOP.
+ * This is useful for architectures with an expensive cpu_relax().
+ */
+#ifndef arch_mutex_cpu_relax
+# define arch_mutex_cpu_relax() cpu_relax()
+#endif
+
 /*
  * Note that the "cmpxchg()" reloads the "old" value for the
  * failure case.
        while (likely(arch_spin_value_unlocked(old.lock.rlock.raw_lock))) {     \
                struct lockref new = old, prev = old;                           \
                CODE                                                            \
-               old.lock_count = cmpxchg(&lockref->lock_count,                  \
-                                        old.lock_count, new.lock_count);       \
+               old.lock_count = cmpxchg64_relaxed(&lockref->lock_count,        \
+                                                  old.lock_count,              \
+                                                  new.lock_count);             \
                if (likely(old.lock_count == prev.lock_count)) {                \
                        SUCCESS;                                                \
                }                                                               \
-               cpu_relax();                                                    \
+               arch_mutex_cpu_relax();                                         \
        }                                                                       \
 } while (0)
 
index 026771a9b0976068f64935b60c9da8526dbe7b63..394838f489ebae1b9d00660af54ceac857538653 100644 (file)
@@ -183,7 +183,7 @@ config MEMORY_HOTPLUG_SPARSE
 config MEMORY_HOTREMOVE
        bool "Allow for memory hot remove"
        select MEMORY_ISOLATION
-       select HAVE_BOOTMEM_INFO_NODE if X86_64
+       select HAVE_BOOTMEM_INFO_NODE if (X86_64 || PPC64)
        depends on MEMORY_HOTPLUG && ARCH_ENABLE_MEMORY_HOTREMOVE
        depends on MIGRATION
 
index c9f0a4339a7dafc2ba7295e49ad8fcdda8fa13de..5a7d58fb883bfa1c4917e48d251cd132c8d9baf9 100644 (file)
@@ -204,6 +204,8 @@ static void __blk_queue_bounce(struct request_queue *q, struct bio **bio_orig,
        struct bio_vec *to, *from;
        unsigned i;
 
+       if (force)
+               goto bounce;
        bio_for_each_segment(from, *bio_orig, i)
                if (page_to_pfn(from->bv_page) > queue_bounce_pfn(q))
                        goto bounce;
index c43789388cd8667536bfd9644a5bbe2cd0d35f3e..b5326b141a251905a96cd5cd995063a29ca20f91 100644 (file)
@@ -677,6 +677,13 @@ static void isolate_freepages(struct zone *zone,
                                        pfn -= pageblock_nr_pages) {
                unsigned long isolated;
 
+               /*
+                * This can iterate a massively long zone without finding any
+                * suitable migration targets, so periodically check if we need
+                * to schedule.
+                */
+               cond_resched();
+
                if (!pfn_valid(pfn))
                        continue;
 
index afc2daa91c609dd8aab70f50fb58fd9100ed8326..4c84678371eb5b5905cc8c4386b512ec57e4f5e3 100644 (file)
@@ -20,8 +20,6 @@ static int hwpoison_inject(void *data, u64 val)
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       if (!hwpoison_filter_enable)
-               goto inject;
        if (!pfn_valid(pfn))
                return -ENXIO;
 
@@ -33,6 +31,9 @@ static int hwpoison_inject(void *data, u64 val)
        if (!get_page_unless_zero(hpage))
                return 0;
 
+       if (!hwpoison_filter_enable)
+               goto inject;
+
        if (!PageLRU(p) && !PageHuge(p))
                shake_page(p, 0);
        /*
index 6975bc812542d2c13642363d928005f355199c54..539eeb96b323bf649f83783e0dddcb4f907e1d6e 100644 (file)
@@ -343,10 +343,11 @@ static long madvise_remove(struct vm_area_struct *vma,
  */
 static int madvise_hwpoison(int bhv, unsigned long start, unsigned long end)
 {
+       struct page *p;
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
-       for (; start < end; start += PAGE_SIZE) {
-               struct page *p;
+       for (; start < end; start += PAGE_SIZE <<
+                               compound_order(compound_head(p))) {
                int ret;
 
                ret = get_user_pages_fast(start, 1, 0, &p);
index d5ff3ce13029b2c99b4ed402898ae0c76a143fde..1c52ddbc839ba1f8f42e940c51bc321ba6b2abfe 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/limits.h>
 #include <linux/export.h>
 #include <linux/mutex.h>
+#include <linux/rbtree.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/swapops.h>
@@ -160,6 +161,10 @@ struct mem_cgroup_per_zone {
 
        struct mem_cgroup_reclaim_iter reclaim_iter[DEF_PRIORITY + 1];
 
+       struct rb_node          tree_node;      /* RB tree node */
+       unsigned long long      usage_in_excess;/* Set to the value by which */
+                                               /* the soft limit is exceeded*/
+       bool                    on_tree;
        struct mem_cgroup       *memcg;         /* Back pointer, we cannot */
                                                /* use container_of        */
 };
@@ -168,6 +173,26 @@ struct mem_cgroup_per_node {
        struct mem_cgroup_per_zone zoneinfo[MAX_NR_ZONES];
 };
 
+/*
+ * Cgroups above their limits are maintained in a RB-Tree, independent of
+ * their hierarchy representation
+ */
+
+struct mem_cgroup_tree_per_zone {
+       struct rb_root rb_root;
+       spinlock_t lock;
+};
+
+struct mem_cgroup_tree_per_node {
+       struct mem_cgroup_tree_per_zone rb_tree_per_zone[MAX_NR_ZONES];
+};
+
+struct mem_cgroup_tree {
+       struct mem_cgroup_tree_per_node *rb_tree_per_node[MAX_NUMNODES];
+};
+
+static struct mem_cgroup_tree soft_limit_tree __read_mostly;
+
 struct mem_cgroup_threshold {
        struct eventfd_ctx *eventfd;
        u64 threshold;
@@ -303,22 +328,6 @@ struct mem_cgroup {
        atomic_t        numainfo_events;
        atomic_t        numainfo_updating;
 #endif
-       /*
-        * Protects soft_contributed transitions.
-        * See mem_cgroup_update_soft_limit
-        */
-       spinlock_t soft_lock;
-
-       /*
-        * If true then this group has increased parents' children_in_excess
-        * when it got over the soft limit.
-        * When a group falls bellow the soft limit, parents' children_in_excess
-        * is decreased and soft_contributed changed to false.
-        */
-       bool soft_contributed;
-
-       /* Number of children that are in soft limit excess */
-       atomic_t children_in_excess;
 
        struct mem_cgroup_per_node *nodeinfo[0];
        /* WARNING: nodeinfo must be the last member here */
@@ -422,6 +431,7 @@ static bool move_file(void)
  * limit reclaim to prevent infinite loops, if they ever occur.
  */
 #define        MEM_CGROUP_MAX_RECLAIM_LOOPS            100
+#define        MEM_CGROUP_MAX_SOFT_LIMIT_RECLAIM_LOOPS 2
 
 enum charge_type {
        MEM_CGROUP_CHARGE_TYPE_CACHE = 0,
@@ -648,6 +658,164 @@ page_cgroup_zoneinfo(struct mem_cgroup *memcg, struct page *page)
        return mem_cgroup_zoneinfo(memcg, nid, zid);
 }
 
+static struct mem_cgroup_tree_per_zone *
+soft_limit_tree_node_zone(int nid, int zid)
+{
+       return &soft_limit_tree.rb_tree_per_node[nid]->rb_tree_per_zone[zid];
+}
+
+static struct mem_cgroup_tree_per_zone *
+soft_limit_tree_from_page(struct page *page)
+{
+       int nid = page_to_nid(page);
+       int zid = page_zonenum(page);
+
+       return &soft_limit_tree.rb_tree_per_node[nid]->rb_tree_per_zone[zid];
+}
+
+static void
+__mem_cgroup_insert_exceeded(struct mem_cgroup *memcg,
+                               struct mem_cgroup_per_zone *mz,
+                               struct mem_cgroup_tree_per_zone *mctz,
+                               unsigned long long new_usage_in_excess)
+{
+       struct rb_node **p = &mctz->rb_root.rb_node;
+       struct rb_node *parent = NULL;
+       struct mem_cgroup_per_zone *mz_node;
+
+       if (mz->on_tree)
+               return;
+
+       mz->usage_in_excess = new_usage_in_excess;
+       if (!mz->usage_in_excess)
+               return;
+       while (*p) {
+               parent = *p;
+               mz_node = rb_entry(parent, struct mem_cgroup_per_zone,
+                                       tree_node);
+               if (mz->usage_in_excess < mz_node->usage_in_excess)
+                       p = &(*p)->rb_left;
+               /*
+                * We can't avoid mem cgroups that are over their soft
+                * limit by the same amount
+                */
+               else if (mz->usage_in_excess >= mz_node->usage_in_excess)
+                       p = &(*p)->rb_right;
+       }
+       rb_link_node(&mz->tree_node, parent, p);
+       rb_insert_color(&mz->tree_node, &mctz->rb_root);
+       mz->on_tree = true;
+}
+
+static void
+__mem_cgroup_remove_exceeded(struct mem_cgroup *memcg,
+                               struct mem_cgroup_per_zone *mz,
+                               struct mem_cgroup_tree_per_zone *mctz)
+{
+       if (!mz->on_tree)
+               return;
+       rb_erase(&mz->tree_node, &mctz->rb_root);
+       mz->on_tree = false;
+}
+
+static void
+mem_cgroup_remove_exceeded(struct mem_cgroup *memcg,
+                               struct mem_cgroup_per_zone *mz,
+                               struct mem_cgroup_tree_per_zone *mctz)
+{
+       spin_lock(&mctz->lock);
+       __mem_cgroup_remove_exceeded(memcg, mz, mctz);
+       spin_unlock(&mctz->lock);
+}
+
+
+static void mem_cgroup_update_tree(struct mem_cgroup *memcg, struct page *page)
+{
+       unsigned long long excess;
+       struct mem_cgroup_per_zone *mz;
+       struct mem_cgroup_tree_per_zone *mctz;
+       int nid = page_to_nid(page);
+       int zid = page_zonenum(page);
+       mctz = soft_limit_tree_from_page(page);
+
+       /*
+        * Necessary to update all ancestors when hierarchy is used.
+        * because their event counter is not touched.
+        */
+       for (; memcg; memcg = parent_mem_cgroup(memcg)) {
+               mz = mem_cgroup_zoneinfo(memcg, nid, zid);
+               excess = res_counter_soft_limit_excess(&memcg->res);
+               /*
+                * We have to update the tree if mz is on RB-tree or
+                * mem is over its softlimit.
+                */
+               if (excess || mz->on_tree) {
+                       spin_lock(&mctz->lock);
+                       /* if on-tree, remove it */
+                       if (mz->on_tree)
+                               __mem_cgroup_remove_exceeded(memcg, mz, mctz);
+                       /*
+                        * Insert again. mz->usage_in_excess will be updated.
+                        * If excess is 0, no tree ops.
+                        */
+                       __mem_cgroup_insert_exceeded(memcg, mz, mctz, excess);
+                       spin_unlock(&mctz->lock);
+               }
+       }
+}
+
+static void mem_cgroup_remove_from_trees(struct mem_cgroup *memcg)
+{
+       int node, zone;
+       struct mem_cgroup_per_zone *mz;
+       struct mem_cgroup_tree_per_zone *mctz;
+
+       for_each_node(node) {
+               for (zone = 0; zone < MAX_NR_ZONES; zone++) {
+                       mz = mem_cgroup_zoneinfo(memcg, node, zone);
+                       mctz = soft_limit_tree_node_zone(node, zone);
+                       mem_cgroup_remove_exceeded(memcg, mz, mctz);
+               }
+       }
+}
+
+static struct mem_cgroup_per_zone *
+__mem_cgroup_largest_soft_limit_node(struct mem_cgroup_tree_per_zone *mctz)
+{
+       struct rb_node *rightmost = NULL;
+       struct mem_cgroup_per_zone *mz;
+
+retry:
+       mz = NULL;
+       rightmost = rb_last(&mctz->rb_root);
+       if (!rightmost)
+               goto done;              /* Nothing to reclaim from */
+
+       mz = rb_entry(rightmost, struct mem_cgroup_per_zone, tree_node);
+       /*
+        * Remove the node now but someone else can add it back,
+        * we will to add it back at the end of reclaim to its correct
+        * position in the tree.
+        */
+       __mem_cgroup_remove_exceeded(mz->memcg, mz, mctz);
+       if (!res_counter_soft_limit_excess(&mz->memcg->res) ||
+               !css_tryget(&mz->memcg->css))
+               goto retry;
+done:
+       return mz;
+}
+
+static struct mem_cgroup_per_zone *
+mem_cgroup_largest_soft_limit_node(struct mem_cgroup_tree_per_zone *mctz)
+{
+       struct mem_cgroup_per_zone *mz;
+
+       spin_lock(&mctz->lock);
+       mz = __mem_cgroup_largest_soft_limit_node(mctz);
+       spin_unlock(&mctz->lock);
+       return mz;
+}
+
 /*
  * Implementation Note: reading percpu statistics for memcg.
  *
@@ -821,48 +989,6 @@ static bool mem_cgroup_event_ratelimit(struct mem_cgroup *memcg,
        return false;
 }
 
-/*
- * Called from rate-limited memcg_check_events when enough
- * MEM_CGROUP_TARGET_SOFTLIMIT events are accumulated and it makes sure
- * that all the parents up the hierarchy will be notified that this group
- * is in excess or that it is not in excess anymore. mmecg->soft_contributed
- * makes the transition a single action whenever the state flips from one to
- * the other.
- */
-static void mem_cgroup_update_soft_limit(struct mem_cgroup *memcg)
-{
-       unsigned long long excess = res_counter_soft_limit_excess(&memcg->res);
-       struct mem_cgroup *parent = memcg;
-       int delta = 0;
-
-       spin_lock(&memcg->soft_lock);
-       if (excess) {
-               if (!memcg->soft_contributed) {
-                       delta = 1;
-                       memcg->soft_contributed = true;
-               }
-       } else {
-               if (memcg->soft_contributed) {
-                       delta = -1;
-                       memcg->soft_contributed = false;
-               }
-       }
-
-       /*
-        * Necessary to update all ancestors when hierarchy is used
-        * because their event counter is not touched.
-        * We track children even outside the hierarchy for the root
-        * cgroup because tree walk starting at root should visit
-        * all cgroups and we want to prevent from pointless tree
-        * walk if no children is below the limit.
-        */
-       while (delta && (parent = parent_mem_cgroup(parent)))
-               atomic_add(delta, &parent->children_in_excess);
-       if (memcg != root_mem_cgroup && !root_mem_cgroup->use_hierarchy)
-               atomic_add(delta, &root_mem_cgroup->children_in_excess);
-       spin_unlock(&memcg->soft_lock);
-}
-
 /*
  * Check events in order.
  *
@@ -886,7 +1012,7 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page)
 
                mem_cgroup_threshold(memcg);
                if (unlikely(do_softlimit))
-                       mem_cgroup_update_soft_limit(memcg);
+                       mem_cgroup_update_tree(memcg, page);
 #if MAX_NUMNODES > 1
                if (unlikely(do_numainfo))
                        atomic_inc(&memcg->numainfo_events);
@@ -929,15 +1055,6 @@ struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm)
        return memcg;
 }
 
-static enum mem_cgroup_filter_t
-mem_cgroup_filter(struct mem_cgroup *memcg, struct mem_cgroup *root,
-               mem_cgroup_iter_filter cond)
-{
-       if (!cond)
-               return VISIT;
-       return cond(memcg, root);
-}
-
 /*
  * Returns a next (in a pre-order walk) alive memcg (with elevated css
  * ref. count) or NULL if the whole root's subtree has been visited.
@@ -945,7 +1062,7 @@ mem_cgroup_filter(struct mem_cgroup *memcg, struct mem_cgroup *root,
  * helper function to be used by mem_cgroup_iter
  */
 static struct mem_cgroup *__mem_cgroup_iter_next(struct mem_cgroup *root,
-               struct mem_cgroup *last_visited, mem_cgroup_iter_filter cond)
+               struct mem_cgroup *last_visited)
 {
        struct cgroup_subsys_state *prev_css, *next_css;
 
@@ -963,31 +1080,11 @@ skip_node:
        if (next_css) {
                struct mem_cgroup *mem = mem_cgroup_from_css(next_css);
 
-               switch (mem_cgroup_filter(mem, root, cond)) {
-               case SKIP:
+               if (css_tryget(&mem->css))
+                       return mem;
+               else {
                        prev_css = next_css;
                        goto skip_node;
-               case SKIP_TREE:
-                       if (mem == root)
-                               return NULL;
-                       /*
-                        * css_rightmost_descendant is not an optimal way to
-                        * skip through a subtree (especially for imbalanced
-                        * trees leaning to right) but that's what we have right
-                        * now. More effective solution would be traversing
-                        * right-up for first non-NULL without calling
-                        * css_next_descendant_pre afterwards.
-                        */
-                       prev_css = css_rightmost_descendant(next_css);
-                       goto skip_node;
-               case VISIT:
-                       if (css_tryget(&mem->css))
-                               return mem;
-                       else {
-                               prev_css = next_css;
-                               goto skip_node;
-                       }
-                       break;
                }
        }
 
@@ -1051,7 +1148,6 @@ static void mem_cgroup_iter_update(struct mem_cgroup_reclaim_iter *iter,
  * @root: hierarchy root
  * @prev: previously returned memcg, NULL on first invocation
  * @reclaim: cookie for shared reclaim walks, NULL for full walks
- * @cond: filter for visited nodes, NULL for no filter
  *
  * Returns references to children of the hierarchy below @root, or
  * @root itself, or %NULL after a full round-trip.
@@ -1064,18 +1160,15 @@ static void mem_cgroup_iter_update(struct mem_cgroup_reclaim_iter *iter,
  * divide up the memcgs in the hierarchy among all concurrent
  * reclaimers operating on the same zone and priority.
  */
-struct mem_cgroup *mem_cgroup_iter_cond(struct mem_cgroup *root,
+struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root,
                                   struct mem_cgroup *prev,
-                                  struct mem_cgroup_reclaim_cookie *reclaim,
-                                  mem_cgroup_iter_filter cond)
+                                  struct mem_cgroup_reclaim_cookie *reclaim)
 {
        struct mem_cgroup *memcg = NULL;
        struct mem_cgroup *last_visited = NULL;
 
-       if (mem_cgroup_disabled()) {
-               /* first call must return non-NULL, second return NULL */
-               return (struct mem_cgroup *)(unsigned long)!prev;
-       }
+       if (mem_cgroup_disabled())
+               return NULL;
 
        if (!root)
                root = root_mem_cgroup;
@@ -1086,9 +1179,7 @@ struct mem_cgroup *mem_cgroup_iter_cond(struct mem_cgroup *root,
        if (!root->use_hierarchy && root != root_mem_cgroup) {
                if (prev)
                        goto out_css_put;
-               if (mem_cgroup_filter(root, root, cond) == VISIT)
-                       return root;
-               return NULL;
+               return root;
        }
 
        rcu_read_lock();
@@ -1111,7 +1202,7 @@ struct mem_cgroup *mem_cgroup_iter_cond(struct mem_cgroup *root,
                        last_visited = mem_cgroup_iter_load(iter, root, &seq);
                }
 
-               memcg = __mem_cgroup_iter_next(root, last_visited, cond);
+               memcg = __mem_cgroup_iter_next(root, last_visited);
 
                if (reclaim) {
                        mem_cgroup_iter_update(iter, last_visited, memcg, seq);
@@ -1122,11 +1213,7 @@ struct mem_cgroup *mem_cgroup_iter_cond(struct mem_cgroup *root,
                                reclaim->generation = iter->generation;
                }
 
-               /*
-                * We have finished the whole tree walk or no group has been
-                * visited because filter told us to skip the root node.
-                */
-               if (!memcg && (prev || (cond && !last_visited)))
+               if (prev && !memcg)
                        goto out_unlock;
        }
 out_unlock:
@@ -1767,7 +1854,6 @@ static unsigned long mem_cgroup_reclaim(struct mem_cgroup *memcg,
        return total;
 }
 
-#if MAX_NUMNODES > 1
 /**
  * test_mem_cgroup_node_reclaimable
  * @memcg: the target memcg
@@ -1790,6 +1876,7 @@ static bool test_mem_cgroup_node_reclaimable(struct mem_cgroup *memcg,
        return false;
 
 }
+#if MAX_NUMNODES > 1
 
 /*
  * Always updating the nodemask is not very good - even if we have an empty
@@ -1857,50 +1944,104 @@ int mem_cgroup_select_victim_node(struct mem_cgroup *memcg)
        return node;
 }
 
+/*
+ * Check all nodes whether it contains reclaimable pages or not.
+ * For quick scan, we make use of scan_nodes. This will allow us to skip
+ * unused nodes. But scan_nodes is lazily updated and may not cotain
+ * enough new information. We need to do double check.
+ */
+static bool mem_cgroup_reclaimable(struct mem_cgroup *memcg, bool noswap)
+{
+       int nid;
+
+       /*
+        * quick check...making use of scan_node.
+        * We can skip unused nodes.
+        */
+       if (!nodes_empty(memcg->scan_nodes)) {
+               for (nid = first_node(memcg->scan_nodes);
+                    nid < MAX_NUMNODES;
+                    nid = next_node(nid, memcg->scan_nodes)) {
+
+                       if (test_mem_cgroup_node_reclaimable(memcg, nid, noswap))
+                               return true;
+               }
+       }
+       /*
+        * Check rest of nodes.
+        */
+       for_each_node_state(nid, N_MEMORY) {
+               if (node_isset(nid, memcg->scan_nodes))
+                       continue;
+               if (test_mem_cgroup_node_reclaimable(memcg, nid, noswap))
+                       return true;
+       }
+       return false;
+}
+
 #else
 int mem_cgroup_select_victim_node(struct mem_cgroup *memcg)
 {
        return 0;
 }
 
-#endif
-
-/*
- * A group is eligible for the soft limit reclaim under the given root
- * hierarchy if
- *     a) it is over its soft limit
- *     b) any parent up the hierarchy is over its soft limit
- *
- * If the given group doesn't have any children over the limit then it
- * doesn't make any sense to iterate its subtree.
- */
-enum mem_cgroup_filter_t
-mem_cgroup_soft_reclaim_eligible(struct mem_cgroup *memcg,
-               struct mem_cgroup *root)
+static bool mem_cgroup_reclaimable(struct mem_cgroup *memcg, bool noswap)
 {
-       struct mem_cgroup *parent;
-
-       if (!memcg)
-               memcg = root_mem_cgroup;
-       parent = memcg;
-
-       if (res_counter_soft_limit_excess(&memcg->res))
-               return VISIT;
+       return test_mem_cgroup_node_reclaimable(memcg, 0, noswap);
+}
+#endif
 
-       /*
-        * If any parent up to the root in the hierarchy is over its soft limit
-        * then we have to obey and reclaim from this group as well.
-        */
-       while ((parent = parent_mem_cgroup(parent))) {
-               if (res_counter_soft_limit_excess(&parent->res))
-                       return VISIT;
-               if (parent == root)
+static int mem_cgroup_soft_reclaim(struct mem_cgroup *root_memcg,
+                                  struct zone *zone,
+                                  gfp_t gfp_mask,
+                                  unsigned long *total_scanned)
+{
+       struct mem_cgroup *victim = NULL;
+       int total = 0;
+       int loop = 0;
+       unsigned long excess;
+       unsigned long nr_scanned;
+       struct mem_cgroup_reclaim_cookie reclaim = {
+               .zone = zone,
+               .priority = 0,
+       };
+
+       excess = res_counter_soft_limit_excess(&root_memcg->res) >> PAGE_SHIFT;
+
+       while (1) {
+               victim = mem_cgroup_iter(root_memcg, victim, &reclaim);
+               if (!victim) {
+                       loop++;
+                       if (loop >= 2) {
+                               /*
+                                * If we have not been able to reclaim
+                                * anything, it might because there are
+                                * no reclaimable pages under this hierarchy
+                                */
+                               if (!total)
+                                       break;
+                               /*
+                                * We want to do more targeted reclaim.
+                                * excess >> 2 is not to excessive so as to
+                                * reclaim too much, nor too less that we keep
+                                * coming back to reclaim from this cgroup
+                                */
+                               if (total >= (excess >> 2) ||
+                                       (loop > MEM_CGROUP_MAX_RECLAIM_LOOPS))
+                                       break;
+                       }
+                       continue;
+               }
+               if (!mem_cgroup_reclaimable(victim, false))
+                       continue;
+               total += mem_cgroup_shrink_node_zone(victim, gfp_mask, false,
+                                                    zone, &nr_scanned);
+               *total_scanned += nr_scanned;
+               if (!res_counter_soft_limit_excess(&root_memcg->res))
                        break;
        }
-
-       if (!atomic_read(&memcg->children_in_excess))
-               return SKIP_TREE;
-       return SKIP;
+       mem_cgroup_iter_break(root_memcg, victim);
+       return total;
 }
 
 static DEFINE_SPINLOCK(memcg_oom_lock);
@@ -2812,7 +2953,9 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg,
        unlock_page_cgroup(pc);
 
        /*
-        * "charge_statistics" updated event counter.
+        * "charge_statistics" updated event counter. Then, check it.
+        * Insert ancestor (and ancestor's ancestors), to softlimit RB-tree.
+        * if they exceeds softlimit.
         */
        memcg_check_events(memcg, page);
 }
@@ -4647,6 +4790,98 @@ static int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg,
        return ret;
 }
 
+unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
+                                           gfp_t gfp_mask,
+                                           unsigned long *total_scanned)
+{
+       unsigned long nr_reclaimed = 0;
+       struct mem_cgroup_per_zone *mz, *next_mz = NULL;
+       unsigned long reclaimed;
+       int loop = 0;
+       struct mem_cgroup_tree_per_zone *mctz;
+       unsigned long long excess;
+       unsigned long nr_scanned;
+
+       if (order > 0)
+               return 0;
+
+       mctz = soft_limit_tree_node_zone(zone_to_nid(zone), zone_idx(zone));
+       /*
+        * This loop can run a while, specially if mem_cgroup's continuously
+        * keep exceeding their soft limit and putting the system under
+        * pressure
+        */
+       do {
+               if (next_mz)
+                       mz = next_mz;
+               else
+                       mz = mem_cgroup_largest_soft_limit_node(mctz);
+               if (!mz)
+                       break;
+
+               nr_scanned = 0;
+               reclaimed = mem_cgroup_soft_reclaim(mz->memcg, zone,
+                                                   gfp_mask, &nr_scanned);
+               nr_reclaimed += reclaimed;
+               *total_scanned += nr_scanned;
+               spin_lock(&mctz->lock);
+
+               /*
+                * If we failed to reclaim anything from this memory cgroup
+                * it is time to move on to the next cgroup
+                */
+               next_mz = NULL;
+               if (!reclaimed) {
+                       do {
+                               /*
+                                * Loop until we find yet another one.
+                                *
+                                * By the time we get the soft_limit lock
+                                * again, someone might have aded the
+                                * group back on the RB tree. Iterate to
+                                * make sure we get a different mem.
+                                * mem_cgroup_largest_soft_limit_node returns
+                                * NULL if no other cgroup is present on
+                                * the tree
+                                */
+                               next_mz =
+                               __mem_cgroup_largest_soft_limit_node(mctz);
+                               if (next_mz == mz)
+                                       css_put(&next_mz->memcg->css);
+                               else /* next_mz == NULL or other memcg */
+                                       break;
+                       } while (1);
+               }
+               __mem_cgroup_remove_exceeded(mz->memcg, mz, mctz);
+               excess = res_counter_soft_limit_excess(&mz->memcg->res);
+               /*
+                * One school of thought says that we should not add
+                * back the node to the tree if reclaim returns 0.
+                * But our reclaim could return 0, simply because due
+                * to priority we are exposing a smaller subset of
+                * memory to reclaim from. Consider this as a longer
+                * term TODO.
+                */
+               /* If excess == 0, no tree ops */
+               __mem_cgroup_insert_exceeded(mz->memcg, mz, mctz, excess);
+               spin_unlock(&mctz->lock);
+               css_put(&mz->memcg->css);
+               loop++;
+               /*
+                * Could not reclaim anything and there are no more
+                * mem cgroups to try or we seem to be looping without
+                * reclaiming anything.
+                */
+               if (!nr_reclaimed &&
+                       (next_mz == NULL ||
+                       loop > MEM_CGROUP_MAX_SOFT_LIMIT_RECLAIM_LOOPS))
+                       break;
+       } while (!nr_reclaimed);
+       if (next_mz)
+               css_put(&next_mz->memcg->css);
+       return nr_reclaimed;
+}
+
 /**
  * mem_cgroup_force_empty_list - clears LRU of a group
  * @memcg: group to clear
@@ -5911,6 +6146,8 @@ static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
        for (zone = 0; zone < MAX_NR_ZONES; zone++) {
                mz = &pn->zoneinfo[zone];
                lruvec_init(&mz->lruvec);
+               mz->usage_in_excess = 0;
+               mz->on_tree = false;
                mz->memcg = memcg;
        }
        memcg->nodeinfo[node] = pn;
@@ -5966,6 +6203,7 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg)
        int node;
        size_t size = memcg_size();
 
+       mem_cgroup_remove_from_trees(memcg);
        free_css_id(&mem_cgroup_subsys, &memcg->css);
 
        for_each_node(node)
@@ -6002,6 +6240,29 @@ struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *memcg)
 }
 EXPORT_SYMBOL(parent_mem_cgroup);
 
+static void __init mem_cgroup_soft_limit_tree_init(void)
+{
+       struct mem_cgroup_tree_per_node *rtpn;
+       struct mem_cgroup_tree_per_zone *rtpz;
+       int tmp, node, zone;
+
+       for_each_node(node) {
+               tmp = node;
+               if (!node_state(node, N_NORMAL_MEMORY))
+                       tmp = -1;
+               rtpn = kzalloc_node(sizeof(*rtpn), GFP_KERNEL, tmp);
+               BUG_ON(!rtpn);
+
+               soft_limit_tree.rb_tree_per_node[node] = rtpn;
+
+               for (zone = 0; zone < MAX_NR_ZONES; zone++) {
+                       rtpz = &rtpn->rb_tree_per_zone[zone];
+                       rtpz->rb_root = RB_ROOT;
+                       spin_lock_init(&rtpz->lock);
+               }
+       }
+}
+
 static struct cgroup_subsys_state * __ref
 mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
 {
@@ -6031,7 +6292,6 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
        mutex_init(&memcg->thresholds_lock);
        spin_lock_init(&memcg->move_lock);
        vmpressure_init(&memcg->vmpressure);
-       spin_lock_init(&memcg->soft_lock);
 
        return &memcg->css;
 
@@ -6109,13 +6369,6 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
 
        mem_cgroup_invalidate_reclaim_iterators(memcg);
        mem_cgroup_reparent_charges(memcg);
-       if (memcg->soft_contributed) {
-               while ((memcg = parent_mem_cgroup(memcg)))
-                       atomic_dec(&memcg->children_in_excess);
-
-               if (memcg != root_mem_cgroup && !root_mem_cgroup->use_hierarchy)
-                       atomic_dec(&root_mem_cgroup->children_in_excess);
-       }
        mem_cgroup_destroy_all_caches(memcg);
        vmpressure_cleanup(&memcg->vmpressure);
 }
@@ -6790,6 +7043,7 @@ static int __init mem_cgroup_init(void)
 {
        hotcpu_notifier(memcg_cpu_hotplug_callback, 0);
        enable_swap_cgroup();
+       mem_cgroup_soft_limit_tree_init();
        memcg_stock_init();
        return 0;
 }
index 947ed5413279261a830eeaeb42d9392aea0f8fa8..bf3351b5115e54915a3d7eaa718d10a9771b2c5f 100644 (file)
@@ -1114,8 +1114,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
                         * shake_page could have turned it free.
                         */
                        if (is_free_buddy_page(p)) {
-                               action_result(pfn, "free buddy, 2nd try",
-                                               DELAYED);
+                               if (flags & MF_COUNT_INCREASED)
+                                       action_result(pfn, "free buddy", DELAYED);
+                               else
+                                       action_result(pfn, "free buddy, 2nd try", DELAYED);
                                return 0;
                        }
                        action_result(pfn, "non LRU", IGNORED);
@@ -1349,7 +1351,7 @@ int unpoison_memory(unsigned long pfn)
         * worked by memory_failure() and the page lock is not held yet.
         * In such case, we yield to memory_failure() and make unpoison fail.
         */
-       if (PageTransHuge(page)) {
+       if (!PageHuge(page) && PageTransHuge(page)) {
                pr_info("MCE: Memory failure is now running on %#lx\n", pfn);
                        return 0;
        }
index 9c8d5f59d30bb87e63c9990c085eb646e69b4ed7..a26bccd44ccb0a907662c08135399462bd816b9c 100644 (file)
@@ -107,7 +107,7 @@ void putback_movable_pages(struct list_head *l)
                list_del(&page->lru);
                dec_zone_page_state(page, NR_ISOLATED_ANON +
                                page_is_file_cache(page));
-               if (unlikely(balloon_page_movable(page)))
+               if (unlikely(isolated_balloon_page(page)))
                        balloon_page_putback(page);
                else
                        putback_lru_page(page);
index d63802663242eb6ad13ca2ed065434f24fd7e5d1..d480cd6fc475854259bdd51021d5125dbdfbe479 100644 (file)
@@ -379,10 +379,14 @@ static unsigned long __munlock_pagevec_fill(struct pagevec *pvec,
 
        /*
         * Initialize pte walk starting at the already pinned page where we
-        * are sure that there is a pte.
+        * are sure that there is a pte, as it was pinned under the same
+        * mmap_sem write op.
         */
        pte = get_locked_pte(vma->vm_mm, start, &ptl);
-       end = min(end, pmd_addr_end(start, end));
+       /* Make sure we do not cross the page table boundary */
+       end = pgd_addr_end(start, end);
+       end = pud_addr_end(start, end);
+       end = pmd_addr_end(start, end);
 
        /* The page next to the pinned page is the first we will try to get */
        start += PAGE_SIZE;
@@ -736,6 +740,7 @@ static int do_mlockall(int flags)
 
                /* Ignore errors */
                mlock_fixup(vma, &prev, vma->vm_start, vma->vm_end, newflags);
+               cond_resched();
        }
 out:
        return 0;
index 0ee638f76ebe584cd40d7541bac886b96b03162e..dd886fac451ab6ab7d6a3132fd2587c10538f300 100644 (file)
@@ -6366,10 +6366,6 @@ __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)
                list_del(&page->lru);
                rmv_page_order(page);
                zone->free_area[order].nr_free--;
-#ifdef CONFIG_HIGHMEM
-               if (PageHighMem(page))
-                       totalhigh_pages -= 1 << order;
-#endif
                for (i = 0; i < (1 << order); i++)
                        SetPageReserved((page+i));
                pfn += (1 << order);
index 8ed1b775bdc9cafe9aaf2ab74e4acf842ffe1a9d..53f2f82f83ae0d16bf19646cdb5b3bce5fc4e4cf 100644 (file)
@@ -48,6 +48,7 @@
 #include <asm/div64.h>
 
 #include <linux/swapops.h>
+#include <linux/balloon_compaction.h>
 
 #include "internal.h"
 
@@ -139,23 +140,11 @@ static bool global_reclaim(struct scan_control *sc)
 {
        return !sc->target_mem_cgroup;
 }
-
-static bool mem_cgroup_should_soft_reclaim(struct scan_control *sc)
-{
-       struct mem_cgroup *root = sc->target_mem_cgroup;
-       return !mem_cgroup_disabled() &&
-               mem_cgroup_soft_reclaim_eligible(root, root) != SKIP_TREE;
-}
 #else
 static bool global_reclaim(struct scan_control *sc)
 {
        return true;
 }
-
-static bool mem_cgroup_should_soft_reclaim(struct scan_control *sc)
-{
-       return false;
-}
 #endif
 
 unsigned long zone_reclaimable_pages(struct zone *zone)
@@ -1125,7 +1114,8 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone,
        LIST_HEAD(clean_pages);
 
        list_for_each_entry_safe(page, next, page_list, lru) {
-               if (page_is_file_cache(page) && !PageDirty(page)) {
+               if (page_is_file_cache(page) && !PageDirty(page) &&
+                   !isolated_balloon_page(page)) {
                        ClearPageActive(page);
                        list_move(&page->lru, &clean_pages);
                }
@@ -2176,11 +2166,9 @@ static inline bool should_continue_reclaim(struct zone *zone,
        }
 }
 
-static int
-__shrink_zone(struct zone *zone, struct scan_control *sc, bool soft_reclaim)
+static void shrink_zone(struct zone *zone, struct scan_control *sc)
 {
        unsigned long nr_reclaimed, nr_scanned;
-       int groups_scanned = 0;
 
        do {
                struct mem_cgroup *root = sc->target_mem_cgroup;
@@ -2188,17 +2176,15 @@ __shrink_zone(struct zone *zone, struct scan_control *sc, bool soft_reclaim)
                        .zone = zone,
                        .priority = sc->priority,
                };
-               struct mem_cgroup *memcg = NULL;
-               mem_cgroup_iter_filter filter = (soft_reclaim) ?
-                       mem_cgroup_soft_reclaim_eligible : NULL;
+               struct mem_cgroup *memcg;
 
                nr_reclaimed = sc->nr_reclaimed;
                nr_scanned = sc->nr_scanned;
 
-               while ((memcg = mem_cgroup_iter_cond(root, memcg, &reclaim, filter))) {
+               memcg = mem_cgroup_iter(root, NULL, &reclaim);
+               do {
                        struct lruvec *lruvec;
 
-                       groups_scanned++;
                        lruvec = mem_cgroup_zone_lruvec(zone, memcg);
 
                        shrink_lruvec(lruvec, sc);
@@ -2218,7 +2204,8 @@ __shrink_zone(struct zone *zone, struct scan_control *sc, bool soft_reclaim)
                                mem_cgroup_iter_break(root, memcg);
                                break;
                        }
-               }
+                       memcg = mem_cgroup_iter(root, memcg, &reclaim);
+               } while (memcg);
 
                vmpressure(sc->gfp_mask, sc->target_mem_cgroup,
                           sc->nr_scanned - nr_scanned,
@@ -2226,37 +2213,6 @@ __shrink_zone(struct zone *zone, struct scan_control *sc, bool soft_reclaim)
 
        } while (should_continue_reclaim(zone, sc->nr_reclaimed - nr_reclaimed,
                                         sc->nr_scanned - nr_scanned, sc));
-
-       return groups_scanned;
-}
-
-
-static void shrink_zone(struct zone *zone, struct scan_control *sc)
-{
-       bool do_soft_reclaim = mem_cgroup_should_soft_reclaim(sc);
-       unsigned long nr_scanned = sc->nr_scanned;
-       int scanned_groups;
-
-       scanned_groups = __shrink_zone(zone, sc, do_soft_reclaim);
-       /*
-        * memcg iterator might race with other reclaimer or start from
-        * a incomplete tree walk so the tree walk in __shrink_zone
-        * might have missed groups that are above the soft limit. Try
-        * another loop to catch up with others. Do it just once to
-        * prevent from reclaim latencies when other reclaimers always
-        * preempt this one.
-        */
-       if (do_soft_reclaim && !scanned_groups)
-               __shrink_zone(zone, sc, do_soft_reclaim);
-
-       /*
-        * No group is over the soft limit or those that are do not have
-        * pages in the zone we are reclaiming so we have to reclaim everybody
-        */
-       if (do_soft_reclaim && (sc->nr_scanned == nr_scanned)) {
-               __shrink_zone(zone, sc, false);
-               return;
-       }
 }
 
 /* Returns true if compaction should go ahead for a high-order request */
@@ -2320,6 +2276,8 @@ static bool shrink_zones(struct zonelist *zonelist, struct scan_control *sc)
 {
        struct zoneref *z;
        struct zone *zone;
+       unsigned long nr_soft_reclaimed;
+       unsigned long nr_soft_scanned;
        bool aborted_reclaim = false;
 
        /*
@@ -2359,6 +2317,18 @@ static bool shrink_zones(struct zonelist *zonelist, struct scan_control *sc)
                                        continue;
                                }
                        }
+                       /*
+                        * This steals pages from memory cgroups over softlimit
+                        * and returns the number of reclaimed pages and
+                        * scanned pages. This works for global memory pressure
+                        * and balancing, not for a memcg's limit.
+                        */
+                       nr_soft_scanned = 0;
+                       nr_soft_reclaimed = mem_cgroup_soft_limit_reclaim(zone,
+                                               sc->order, sc->gfp_mask,
+                                               &nr_soft_scanned);
+                       sc->nr_reclaimed += nr_soft_reclaimed;
+                       sc->nr_scanned += nr_soft_scanned;
                        /* need some check for avoid more shrink_zone() */
                }
 
@@ -2952,6 +2922,8 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order,
 {
        int i;
        int end_zone = 0;       /* Inclusive.  0 = ZONE_DMA */
+       unsigned long nr_soft_reclaimed;
+       unsigned long nr_soft_scanned;
        struct scan_control sc = {
                .gfp_mask = GFP_KERNEL,
                .priority = DEF_PRIORITY,
@@ -3066,6 +3038,15 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order,
 
                        sc.nr_scanned = 0;
 
+                       nr_soft_scanned = 0;
+                       /*
+                        * Call soft limit reclaim before calling shrink_zone.
+                        */
+                       nr_soft_reclaimed = mem_cgroup_soft_limit_reclaim(zone,
+                                                       order, sc.gfp_mask,
+                                                       &nr_soft_scanned);
+                       sc.nr_reclaimed += nr_soft_reclaimed;
+
                        /*
                         * There should be no need to raise the scanning
                         * priority if enough pages are already being scanned
index 1eb05d80b07bea736e85a389be0d98c8bfcb3d9c..3ed616215870cf73b4d8a516d52e5da04d9472e5 100644 (file)
 static unsigned int mrp_join_time __read_mostly = 200;
 module_param(mrp_join_time, uint, 0644);
 MODULE_PARM_DESC(mrp_join_time, "Join time in ms (default 200ms)");
+
+static unsigned int mrp_periodic_time __read_mostly = 1000;
+module_param(mrp_periodic_time, uint, 0644);
+MODULE_PARM_DESC(mrp_periodic_time, "Periodic time in ms (default 1s)");
+
 MODULE_LICENSE("GPL");
 
 static const u8
@@ -595,6 +600,24 @@ static void mrp_join_timer(unsigned long data)
        mrp_join_timer_arm(app);
 }
 
+static void mrp_periodic_timer_arm(struct mrp_applicant *app)
+{
+       mod_timer(&app->periodic_timer,
+                 jiffies + msecs_to_jiffies(mrp_periodic_time));
+}
+
+static void mrp_periodic_timer(unsigned long data)
+{
+       struct mrp_applicant *app = (struct mrp_applicant *)data;
+
+       spin_lock(&app->lock);
+       mrp_mad_event(app, MRP_EVENT_PERIODIC);
+       mrp_pdu_queue(app);
+       spin_unlock(&app->lock);
+
+       mrp_periodic_timer_arm(app);
+}
+
 static int mrp_pdu_parse_end_mark(struct sk_buff *skb, int *offset)
 {
        __be16 endmark;
@@ -845,6 +868,9 @@ int mrp_init_applicant(struct net_device *dev, struct mrp_application *appl)
        rcu_assign_pointer(dev->mrp_port->applicants[appl->type], app);
        setup_timer(&app->join_timer, mrp_join_timer, (unsigned long)app);
        mrp_join_timer_arm(app);
+       setup_timer(&app->periodic_timer, mrp_periodic_timer,
+                   (unsigned long)app);
+       mrp_periodic_timer_arm(app);
        return 0;
 
 err3:
@@ -870,6 +896,7 @@ void mrp_uninit_applicant(struct net_device *dev, struct mrp_application *appl)
         * all pending messages before the applicant is gone.
         */
        del_timer_sync(&app->join_timer);
+       del_timer_sync(&app->periodic_timer);
 
        spin_lock_bh(&app->lock);
        mrp_mad_event(app, MRP_EVENT_TX);
index 4493913f0d5c973446e0597b38f9dda2269d3c48..813db4e646021dea4c089d53ea65504a63ff0d2d 100644 (file)
@@ -168,6 +168,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
        case ETH_P_8021Q:
                vhdr = (struct vlan_ethhdr *)skb->data;
                vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
+               vid |= BATADV_VLAN_HAS_TAG;
 
                if (vhdr->h_vlan_encapsulated_proto != ethertype)
                        break;
@@ -331,6 +332,7 @@ void batadv_interface_rx(struct net_device *soft_iface,
        case ETH_P_8021Q:
                vhdr = (struct vlan_ethhdr *)skb->data;
                vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
+               vid |= BATADV_VLAN_HAS_TAG;
 
                if (vhdr->h_vlan_encapsulated_proto != ethertype)
                        break;
index 634debab4d54582f04c69a4664b00c7541696a93..fb7356fcfe51e03664d7aed6458eafd3015634e5 100644 (file)
@@ -1146,7 +1146,11 @@ int hci_dev_open(__u16 dev)
                goto done;
        }
 
-       if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) {
+       /* Check for rfkill but allow the HCI setup stage to proceed
+        * (which in itself doesn't cause any RF activity).
+        */
+       if (test_bit(HCI_RFKILLED, &hdev->dev_flags) &&
+           !test_bit(HCI_SETUP, &hdev->dev_flags)) {
                ret = -ERFKILL;
                goto done;
        }
@@ -1566,10 +1570,13 @@ static int hci_rfkill_set_block(void *data, bool blocked)
 
        BT_DBG("%p name %s blocked %d", hdev, hdev->name, blocked);
 
-       if (!blocked)
-               return 0;
-
-       hci_dev_do_close(hdev);
+       if (blocked) {
+               set_bit(HCI_RFKILLED, &hdev->dev_flags);
+               if (!test_bit(HCI_SETUP, &hdev->dev_flags))
+                       hci_dev_do_close(hdev);
+       } else {
+               clear_bit(HCI_RFKILLED, &hdev->dev_flags);
+       }
 
        return 0;
 }
@@ -1591,9 +1598,13 @@ static void hci_power_on(struct work_struct *work)
                return;
        }
 
-       if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
+       if (test_bit(HCI_RFKILLED, &hdev->dev_flags)) {
+               clear_bit(HCI_AUTO_OFF, &hdev->dev_flags);
+               hci_dev_do_close(hdev);
+       } else if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
                queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
                                   HCI_AUTO_OFF_TIMEOUT);
+       }
 
        if (test_and_clear_bit(HCI_SETUP, &hdev->dev_flags))
                mgmt_index_added(hdev);
@@ -2209,6 +2220,9 @@ int hci_register_dev(struct hci_dev *hdev)
                }
        }
 
+       if (hdev->rfkill && rfkill_blocked(hdev->rfkill))
+               set_bit(HCI_RFKILLED, &hdev->dev_flags);
+
        set_bit(HCI_SETUP, &hdev->dev_flags);
 
        if (hdev->dev_type != HCI_AMP)
index 94aab73f89d4c9e447d2b65f12f8ec71ee1a66e6..8db3e89fae354aebb67c6ea7172a3e2e1926b66d 100644 (file)
@@ -3557,7 +3557,11 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
        cp.handle = cpu_to_le16(conn->handle);
 
        if (ltk->authenticated)
-               conn->sec_level = BT_SECURITY_HIGH;
+               conn->pending_sec_level = BT_SECURITY_HIGH;
+       else
+               conn->pending_sec_level = BT_SECURITY_MEDIUM;
+
+       conn->enc_key_size = ltk->enc_size;
 
        hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
 
index b3bb7bca8e606439edbd9f9838bb8021200bb28c..63fa11109a1c391725d5efec2075c1524d9f1a1a 100644 (file)
@@ -3755,6 +3755,13 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
 
        sk = chan->sk;
 
+       /* For certain devices (ex: HID mouse), support for authentication,
+        * pairing and bonding is optional. For such devices, inorder to avoid
+        * the ACL alive for too long after L2CAP disconnection, reset the ACL
+        * disc_timeout back to HCI_DISCONN_TIMEOUT during L2CAP connect.
+        */
+       conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
+
        bacpy(&bt_sk(sk)->src, conn->src);
        bacpy(&bt_sk(sk)->dst, conn->dst);
        chan->psm  = psm;
index 6d126faf145fe5107fbd0dfd9b810671c34e1e66..84fcf9fff3ea52e4235b7e478deb487fb075b53c 100644 (file)
@@ -569,7 +569,6 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb)
 static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
 {
        struct rfcomm_dev *dev = dlc->owner;
-       struct tty_struct *tty;
        if (!dev)
                return;
 
@@ -581,38 +580,8 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
                            DPM_ORDER_DEV_AFTER_PARENT);
 
                wake_up_interruptible(&dev->port.open_wait);
-       } else if (dlc->state == BT_CLOSED) {
-               tty = tty_port_tty_get(&dev->port);
-               if (!tty) {
-                       if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
-                               /* Drop DLC lock here to avoid deadlock
-                                * 1. rfcomm_dev_get will take rfcomm_dev_lock
-                                *    but in rfcomm_dev_add there's lock order:
-                                *    rfcomm_dev_lock -> dlc lock
-                                * 2. tty_port_put will deadlock if it's
-                                *    the last reference
-                                *
-                                * FIXME: when we release the lock anything
-                                * could happen to dev, even its destruction
-                                */
-                               rfcomm_dlc_unlock(dlc);
-                               if (rfcomm_dev_get(dev->id) == NULL) {
-                                       rfcomm_dlc_lock(dlc);
-                                       return;
-                               }
-
-                               if (!test_and_set_bit(RFCOMM_TTY_RELEASED,
-                                                     &dev->flags))
-                                       tty_port_put(&dev->port);
-
-                               tty_port_put(&dev->port);
-                               rfcomm_dlc_lock(dlc);
-                       }
-               } else {
-                       tty_hangup(tty);
-                       tty_kref_put(tty);
-               }
-       }
+       } else if (dlc->state == BT_CLOSED)
+               tty_port_tty_hangup(&dev->port, false);
 }
 
 static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig)
index b9259efa636ef8fe2b79ec25de49a16efa9034db..e74ddc1c29a8be20f1a093fcc8e27b11bca6f03e 100644 (file)
@@ -207,7 +207,7 @@ int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
               struct net_device *dev, u32 filter_mask)
 {
        int err = 0;
-       struct net_bridge_port *port = br_port_get_rcu(dev);
+       struct net_bridge_port *port = br_port_get_rtnl(dev);
 
        /* not a bridge port and  */
        if (!port && !(filter_mask & RTEXT_FILTER_BRVLAN))
@@ -451,7 +451,7 @@ static size_t br_get_link_af_size(const struct net_device *dev)
        struct net_port_vlans *pv;
 
        if (br_port_exists(dev))
-               pv = nbp_get_vlan_info(br_port_get_rcu(dev));
+               pv = nbp_get_vlan_info(br_port_get_rtnl(dev));
        else if (dev->priv_flags & IFF_EBRIDGE)
                pv = br_get_vlan_info((struct net_bridge *)netdev_priv(dev));
        else
index 598cb0b333c64b57c639dd7cda8df7aec229448d..efb57d91156975b3b43a2afdc588128a2f6e1f79 100644 (file)
@@ -202,13 +202,10 @@ struct net_bridge_port
 
 static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev)
 {
-       struct net_bridge_port *port =
-                       rcu_dereference_rtnl(dev->rx_handler_data);
-
-       return br_port_exists(dev) ? port : NULL;
+       return rcu_dereference(dev->rx_handler_data);
 }
 
-static inline struct net_bridge_port *br_port_get_rtnl(struct net_device *dev)
+static inline struct net_bridge_port *br_port_get_rtnl(const struct net_device *dev)
 {
        return br_port_exists(dev) ?
                rtnl_dereference(dev->rx_handler_data) : NULL;
@@ -746,6 +743,7 @@ extern struct net_bridge_port *br_get_port(struct net_bridge *br,
 extern void br_init_port(struct net_bridge_port *p);
 extern void br_become_designated_port(struct net_bridge_port *p);
 
+extern void __br_set_forward_delay(struct net_bridge *br, unsigned long t);
 extern int br_set_forward_delay(struct net_bridge *br, unsigned long x);
 extern int br_set_hello_time(struct net_bridge *br, unsigned long x);
 extern int br_set_max_age(struct net_bridge *br, unsigned long x);
index 1c0a50f132293e0fb15e506620459047a8e1075b..3c86f0538cbb4a056bc274c971e254cb3d8da0f8 100644 (file)
@@ -209,7 +209,7 @@ static void br_record_config_information(struct net_bridge_port *p,
        p->designated_age = jiffies - bpdu->message_age;
 
        mod_timer(&p->message_age_timer, jiffies
-                 + (p->br->max_age - bpdu->message_age));
+                 + (bpdu->max_age - bpdu->message_age));
 }
 
 /* called under bridge lock */
@@ -544,18 +544,27 @@ int br_set_max_age(struct net_bridge *br, unsigned long val)
 
 }
 
+void __br_set_forward_delay(struct net_bridge *br, unsigned long t)
+{
+       br->bridge_forward_delay = t;
+       if (br_is_root_bridge(br))
+               br->forward_delay = br->bridge_forward_delay;
+}
+
 int br_set_forward_delay(struct net_bridge *br, unsigned long val)
 {
        unsigned long t = clock_t_to_jiffies(val);
+       int err = -ERANGE;
 
+       spin_lock_bh(&br->lock);
        if (br->stp_enabled != BR_NO_STP &&
            (t < BR_MIN_FORWARD_DELAY || t > BR_MAX_FORWARD_DELAY))
-               return -ERANGE;
+               goto unlock;
 
-       spin_lock_bh(&br->lock);
-       br->bridge_forward_delay = t;
-       if (br_is_root_bridge(br))
-               br->forward_delay = br->bridge_forward_delay;
+       __br_set_forward_delay(br, t);
+       err = 0;
+
+unlock:
        spin_unlock_bh(&br->lock);
-       return 0;
+       return err;
 }
index d45e760141bb81a34909b98724b2d8f3fc876136..108084a0467160e30eb001cd2dbb326fdc4dadd3 100644 (file)
@@ -129,6 +129,14 @@ static void br_stp_start(struct net_bridge *br)
        char *envp[] = { NULL };
 
        r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC);
+
+       spin_lock_bh(&br->lock);
+
+       if (br->bridge_forward_delay < BR_MIN_FORWARD_DELAY)
+               __br_set_forward_delay(br, BR_MIN_FORWARD_DELAY);
+       else if (br->bridge_forward_delay < BR_MAX_FORWARD_DELAY)
+               __br_set_forward_delay(br, BR_MAX_FORWARD_DELAY);
+
        if (r == 0) {
                br->stp_enabled = BR_USER_STP;
                br_debug(br, "userspace STP started\n");
@@ -137,10 +145,10 @@ static void br_stp_start(struct net_bridge *br)
                br_debug(br, "using kernel STP\n");
 
                /* To start timers on any ports left in blocking */
-               spin_lock_bh(&br->lock);
                br_port_state_selection(br);
-               spin_unlock_bh(&br->lock);
        }
+
+       spin_unlock_bh(&br->lock);
 }
 
 static void br_stp_stop(struct net_bridge *br)
index 1606f740d6ae0d1b7ea8aeb1ba8126fd7693888d..2b4b32aaa893b3117043e6a218fcde6c58f0aff4 100644 (file)
@@ -2215,6 +2215,17 @@ void ceph_osdc_sync(struct ceph_osd_client *osdc)
 }
 EXPORT_SYMBOL(ceph_osdc_sync);
 
+/*
+ * Call all pending notify callbacks - for use after a watch is
+ * unregistered, to make sure no more callbacks for it will be invoked
+ */
+extern void ceph_osdc_flush_notifies(struct ceph_osd_client *osdc)
+{
+       flush_workqueue(osdc->notify_wq);
+}
+EXPORT_SYMBOL(ceph_osdc_flush_notifies);
+
+
 /*
  * init, shutdown
  */
index 5c713f2239cc6245d230d2e35e243bbee7339761..65f829cfd928b3bda157b0848e13edfa5b118bae 100644 (file)
@@ -5247,10 +5247,12 @@ static int dev_new_index(struct net *net)
 
 /* Delayed registration/unregisteration */
 static LIST_HEAD(net_todo_list);
+static DECLARE_WAIT_QUEUE_HEAD(netdev_unregistering_wq);
 
 static void net_set_todo(struct net_device *dev)
 {
        list_add_tail(&dev->todo_list, &net_todo_list);
+       dev_net(dev)->dev_unreg_count++;
 }
 
 static void rollback_registered_many(struct list_head *head)
@@ -5918,6 +5920,12 @@ void netdev_run_todo(void)
                if (dev->destructor)
                        dev->destructor(dev);
 
+               /* Report a network device has been unregistered */
+               rtnl_lock();
+               dev_net(dev)->dev_unreg_count--;
+               __rtnl_unlock();
+               wake_up(&netdev_unregistering_wq);
+
                /* Free network device */
                kobject_put(&dev->dev.kobj);
        }
@@ -6603,6 +6611,34 @@ static void __net_exit default_device_exit(struct net *net)
        rtnl_unlock();
 }
 
+static void __net_exit rtnl_lock_unregistering(struct list_head *net_list)
+{
+       /* Return with the rtnl_lock held when there are no network
+        * devices unregistering in any network namespace in net_list.
+        */
+       struct net *net;
+       bool unregistering;
+       DEFINE_WAIT(wait);
+
+       for (;;) {
+               prepare_to_wait(&netdev_unregistering_wq, &wait,
+                               TASK_UNINTERRUPTIBLE);
+               unregistering = false;
+               rtnl_lock();
+               list_for_each_entry(net, net_list, exit_list) {
+                       if (net->dev_unreg_count > 0) {
+                               unregistering = true;
+                               break;
+                       }
+               }
+               if (!unregistering)
+                       break;
+               __rtnl_unlock();
+               schedule();
+       }
+       finish_wait(&netdev_unregistering_wq, &wait);
+}
+
 static void __net_exit default_device_exit_batch(struct list_head *net_list)
 {
        /* At exit all network devices most be removed from a network
@@ -6614,7 +6650,18 @@ static void __net_exit default_device_exit_batch(struct list_head *net_list)
        struct net *net;
        LIST_HEAD(dev_kill_list);
 
-       rtnl_lock();
+       /* To prevent network device cleanup code from dereferencing
+        * loopback devices or network devices that have been freed
+        * wait here for all pending unregistrations to complete,
+        * before unregistring the loopback device and allowing the
+        * network namespace be freed.
+        *
+        * The netdev todo list containing all network devices
+        * unregistrations that happen in default_device_exit_batch
+        * will run in the rtnl_unlock() at the end of
+        * default_device_exit_batch.
+        */
+       rtnl_lock_unregistering(net_list);
        list_for_each_entry(net, net_list, exit_list) {
                for_each_netdev_reverse(net, dev) {
                        if (dev->rtnl_link_ops)
index 1929af87b2609650d0b484e7d01dc4a405ba8389..8d7d0dd72db211e23b5bcffd16f7600841841598 100644 (file)
@@ -154,8 +154,8 @@ ipv6:
        if (poff >= 0) {
                __be32 *ports, _ports;
 
-               nhoff += poff;
-               ports = skb_header_pointer(skb, nhoff, sizeof(_ports), &_ports);
+               ports = skb_header_pointer(skb, nhoff + poff,
+                                          sizeof(_ports), &_ports);
                if (ports)
                        flow->ports = *ports;
        }
index 2c637e9a0b277ff2a987edf139622d7580b43e02..fc75c9e461b8d366d5c29417735432dc573f08ae 100644 (file)
@@ -550,7 +550,7 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo
                return;
 
        proto = ntohs(eth_hdr(skb)->h_proto);
-       if (proto == ETH_P_IP) {
+       if (proto == ETH_P_ARP) {
                struct arphdr *arp;
                unsigned char *arp_ptr;
                /* No arp on this interface */
@@ -1284,15 +1284,14 @@ EXPORT_SYMBOL_GPL(__netpoll_free_async);
 
 void netpoll_cleanup(struct netpoll *np)
 {
-       if (!np->dev)
-               return;
-
        rtnl_lock();
+       if (!np->dev)
+               goto out;
        __netpoll_cleanup(np);
-       rtnl_unlock();
-
        dev_put(np->dev);
        np->dev = NULL;
+out:
+       rtnl_unlock();
 }
 EXPORT_SYMBOL(netpoll_cleanup);
 
index 6a2f13cee86a0c3f34f69832d4b6d93592fd5327..3f1ec1586ae174d9bea18de2bcada31c3c88a5bb 100644 (file)
 
 #include <net/secure_seq.h>
 
-static u32 net_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned;
+#define NET_SECRET_SIZE (MD5_MESSAGE_BYTES / 4)
 
-void net_secret_init(void)
+static u32 net_secret[NET_SECRET_SIZE] ____cacheline_aligned;
+
+static void net_secret_init(void)
 {
-       get_random_bytes(net_secret, sizeof(net_secret));
+       u32 tmp;
+       int i;
+
+       if (likely(net_secret[0]))
+               return;
+
+       for (i = NET_SECRET_SIZE; i > 0;) {
+               do {
+                       get_random_bytes(&tmp, sizeof(tmp));
+               } while (!tmp);
+               cmpxchg(&net_secret[--i], 0, tmp);
+       }
 }
 
 #ifdef CONFIG_INET
@@ -42,6 +55,7 @@ __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
        u32 hash[MD5_DIGEST_WORDS];
        u32 i;
 
+       net_secret_init();
        memcpy(hash, saddr, 16);
        for (i = 0; i < 4; i++)
                secret[i] = net_secret[i] + (__force u32)daddr[i];
@@ -63,6 +77,7 @@ u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
        u32 hash[MD5_DIGEST_WORDS];
        u32 i;
 
+       net_secret_init();
        memcpy(hash, saddr, 16);
        for (i = 0; i < 4; i++)
                secret[i] = net_secret[i] + (__force u32) daddr[i];
@@ -82,6 +97,7 @@ __u32 secure_ip_id(__be32 daddr)
 {
        u32 hash[MD5_DIGEST_WORDS];
 
+       net_secret_init();
        hash[0] = (__force __u32) daddr;
        hash[1] = net_secret[13];
        hash[2] = net_secret[14];
@@ -96,6 +112,7 @@ __u32 secure_ipv6_id(const __be32 daddr[4])
 {
        __u32 hash[4];
 
+       net_secret_init();
        memcpy(hash, daddr, 16);
        md5_transform(hash, net_secret);
 
@@ -107,6 +124,7 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
 {
        u32 hash[MD5_DIGEST_WORDS];
 
+       net_secret_init();
        hash[0] = (__force u32)saddr;
        hash[1] = (__force u32)daddr;
        hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
@@ -121,6 +139,7 @@ u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
 {
        u32 hash[MD5_DIGEST_WORDS];
 
+       net_secret_init();
        hash[0] = (__force u32)saddr;
        hash[1] = (__force u32)daddr;
        hash[2] = (__force u32)dport ^ net_secret[14];
@@ -140,6 +159,7 @@ u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
        u32 hash[MD5_DIGEST_WORDS];
        u64 seq;
 
+       net_secret_init();
        hash[0] = (__force u32)saddr;
        hash[1] = (__force u32)daddr;
        hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
@@ -164,6 +184,7 @@ u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
        u64 seq;
        u32 i;
 
+       net_secret_init();
        memcpy(hash, saddr, 16);
        for (i = 0; i < 4; i++)
                secret[i] = net_secret[i] + daddr[i];
index 9c61f9c02fdb81df0f87f62994ac13330631c59a..6cf9f7782ad4238208173f390369b5fc4cc75e2b 100644 (file)
@@ -135,6 +135,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
                if (dst)
                        dst->ops->redirect(dst, sk, skb);
+               goto out;
        }
 
        if (type == ICMPV6_PKT_TOOBIG) {
index 7a1874b7b8fd4431b6cc7d383ae5e96923dbdda3..cfeb85cff4f02abc28570b267ba6e64784595fab 100644 (file)
@@ -263,10 +263,8 @@ void build_ehash_secret(void)
                get_random_bytes(&rnd, sizeof(rnd));
        } while (rnd == 0);
 
-       if (cmpxchg(&inet_ehash_secret, 0, rnd) == 0) {
+       if (cmpxchg(&inet_ehash_secret, 0, rnd) == 0)
                get_random_bytes(&ipv6_hash_secret, sizeof(ipv6_hash_secret));
-               net_secret_init();
-       }
 }
 EXPORT_SYMBOL(build_ehash_secret);
 
index d6c0e64ec97f2147124e84d4b634f263bac9eb95..7defdc9ba16744fd263c539c37f125fc31422c87 100644 (file)
@@ -369,7 +369,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
        pip->saddr    = fl4.saddr;
        pip->protocol = IPPROTO_IGMP;
        pip->tot_len  = 0;      /* filled in later */
-       ip_select_ident(pip, &rt->dst, NULL);
+       ip_select_ident(skb, &rt->dst, NULL);
        ((u8 *)&pip[1])[0] = IPOPT_RA;
        ((u8 *)&pip[1])[1] = 4;
        ((u8 *)&pip[1])[2] = 0;
@@ -714,7 +714,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
        iph->daddr    = dst;
        iph->saddr    = fl4.saddr;
        iph->protocol = IPPROTO_IGMP;
-       ip_select_ident(iph, &rt->dst, NULL);
+       ip_select_ident(skb, &rt->dst, NULL);
        ((u8 *)&iph[1])[0] = IPOPT_RA;
        ((u8 *)&iph[1])[1] = 4;
        ((u8 *)&iph[1])[2] = 0;
@@ -736,7 +736,7 @@ static void igmp_gq_timer_expire(unsigned long data)
 
        in_dev->mr_gq_running = 0;
        igmpv3_send_report(in_dev, NULL);
-       __in_dev_put(in_dev);
+       in_dev_put(in_dev);
 }
 
 static void igmp_ifc_timer_expire(unsigned long data)
@@ -749,7 +749,7 @@ static void igmp_ifc_timer_expire(unsigned long data)
                igmp_ifc_start_timer(in_dev,
                                     unsolicited_report_interval(in_dev));
        }
-       __in_dev_put(in_dev);
+       in_dev_put(in_dev);
 }
 
 static void igmp_ifc_event(struct in_device *in_dev)
index 000e3d239d6481ed230e71c9c9033dba301694e9..33d5537881ed7b39e33199dfe978bbe5b912d706 100644 (file)
@@ -32,8 +32,8 @@
  *  At the moment of writing this notes identifier of IP packets is generated
  *  to be unpredictable using this code only for packets subjected
  *  (actually or potentially) to defragmentation.  I.e. DF packets less than
- *  PMTU in size uses a constant ID and do not use this code (see
- *  ip_select_ident() in include/net/ip.h).
+ *  PMTU in size when local fragmentation is disabled use a constant ID and do
+ *  not use this code (see ip_select_ident() in include/net/ip.h).
  *
  *  Route cache entries hold references to our nodes.
  *  New cache entries get references via lookup by destination IP address in
index 9ee17e3d11c30e4054558729df205b41a762e806..a04d872c54f919c7133e7830773301cdf070f3ed 100644 (file)
@@ -148,7 +148,7 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
        iph->daddr    = (opt && opt->opt.srr ? opt->opt.faddr : daddr);
        iph->saddr    = saddr;
        iph->protocol = sk->sk_protocol;
-       ip_select_ident(iph, &rt->dst, sk);
+       ip_select_ident(skb, &rt->dst, sk);
 
        if (opt && opt->opt.optlen) {
                iph->ihl += opt->opt.optlen>>2;
@@ -386,7 +386,7 @@ packet_routed:
                ip_options_build(skb, &inet_opt->opt, inet->inet_daddr, rt, 0);
        }
 
-       ip_select_ident_more(iph, &rt->dst, sk,
+       ip_select_ident_more(skb, &rt->dst, sk,
                             (skb_shinfo(skb)->gso_segs ?: 1) - 1);
 
        skb->priority = sk->sk_priority;
@@ -1316,7 +1316,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
        else
                ttl = ip_select_ttl(inet, &rt->dst);
 
-       iph = (struct iphdr *)skb->data;
+       iph = ip_hdr(skb);
        iph->version = 4;
        iph->ihl = 5;
        iph->tos = inet->tos;
@@ -1324,7 +1324,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
        iph->ttl = ttl;
        iph->protocol = sk->sk_protocol;
        ip_copy_addrs(iph, fl4);
-       ip_select_ident(iph, &rt->dst, sk);
+       ip_select_ident(skb, &rt->dst, sk);
 
        if (opt) {
                iph->ihl += opt->optlen>>2;
index ac9fabe0300f613e87bbe4d70e9c861fbc95889e..63a6d6d6b87581d3ac3bda52cab5833f3cb169ab 100644 (file)
@@ -623,6 +623,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
                        tunnel->err_count = 0;
        }
 
+       tos = ip_tunnel_ecn_encap(tos, inner_iph, skb);
        ttl = tnl_params->ttl;
        if (ttl == 0) {
                if (skb->protocol == htons(ETH_P_IP))
@@ -641,18 +642,17 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 
        max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr)
                        + rt->dst.header_len;
-       if (max_headroom > dev->needed_headroom) {
+       if (max_headroom > dev->needed_headroom)
                dev->needed_headroom = max_headroom;
-               if (skb_cow_head(skb, dev->needed_headroom)) {
-                       dev->stats.tx_dropped++;
-                       dev_kfree_skb(skb);
-                       return;
-               }
+
+       if (skb_cow_head(skb, dev->needed_headroom)) {
+               dev->stats.tx_dropped++;
+               dev_kfree_skb(skb);
+               return;
        }
 
        err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, protocol,
-                           ip_tunnel_ecn_encap(tos, inner_iph, skb), ttl, df,
-                           !net_eq(tunnel->net, dev_net(dev)));
+                           tos, ttl, df, !net_eq(tunnel->net, dev_net(dev)));
        iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
 
        return;
@@ -853,8 +853,10 @@ int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
        /* FB netdevice is special: we have one, and only one per netns.
         * Allowing to move it to another netns is clearly unsafe.
         */
-       if (!IS_ERR(itn->fb_tunnel_dev))
+       if (!IS_ERR(itn->fb_tunnel_dev)) {
                itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL;
+               ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev));
+       }
        rtnl_unlock();
 
        return PTR_RET(itn->fb_tunnel_dev);
@@ -884,8 +886,6 @@ static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head,
                        if (!net_eq(dev_net(t->dev), net))
                                unregister_netdevice_queue(t->dev, head);
        }
-       if (itn->fb_tunnel_dev)
-               unregister_netdevice_queue(itn->fb_tunnel_dev, head);
 }
 
 void ip_tunnel_delete_net(struct ip_tunnel_net *itn, struct rtnl_link_ops *ops)
index d6c856b17fd4ff22c0034af676a648730dffce82..c31e3ad98ef28e91eff2679d6976d4c20c055410 100644 (file)
@@ -61,7 +61,7 @@ int iptunnel_xmit(struct rtable *rt, struct sk_buff *skb,
        memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
 
        /* Push down and install the IP header. */
-       __skb_push(skb, sizeof(struct iphdr));
+       skb_push(skb, sizeof(struct iphdr));
        skb_reset_network_header(skb);
 
        iph = ip_hdr(skb);
index 9ae54b09254f158d82d6b86adafe04776c830775..62212c772a4b95961dafe1efce3fd06f146ccbb6 100644 (file)
@@ -1658,7 +1658,7 @@ static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr)
        iph->protocol   =       IPPROTO_IPIP;
        iph->ihl        =       5;
        iph->tot_len    =       htons(skb->len);
-       ip_select_ident(iph, skb_dst(skb), NULL);
+       ip_select_ident(skb, skb_dst(skb), NULL);
        ip_send_check(iph);
 
        memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
index 67e17dcda65e64f27b9ca5b244561ab2d7fc594f..b6346bf2fde3bc16f0655e9c9f7c6ade5ffeae8a 100644 (file)
@@ -267,7 +267,8 @@ synproxy_tg4(struct sk_buff *skb, const struct xt_action_param *par)
        if (th == NULL)
                return NF_DROP;
 
-       synproxy_parse_options(skb, par->thoff, th, &opts);
+       if (!synproxy_parse_options(skb, par->thoff, th, &opts))
+               return NF_DROP;
 
        if (th->syn && !(th->ack || th->fin || th->rst)) {
                /* Initial SYN from client */
@@ -350,7 +351,8 @@ static unsigned int ipv4_synproxy_hook(unsigned int hooknum,
 
                /* fall through */
        case TCP_CONNTRACK_SYN_SENT:
-               synproxy_parse_options(skb, thoff, th, &opts);
+               if (!synproxy_parse_options(skb, thoff, th, &opts))
+                       return NF_DROP;
 
                if (!th->syn && th->ack &&
                    CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) {
@@ -373,7 +375,9 @@ static unsigned int ipv4_synproxy_hook(unsigned int hooknum,
                if (!th->syn || !th->ack)
                        break;
 
-               synproxy_parse_options(skb, thoff, th, &opts);
+               if (!synproxy_parse_options(skb, thoff, th, &opts))
+                       return NF_DROP;
+
                if (opts.options & XT_SYNPROXY_OPT_TIMESTAMP)
                        synproxy->tsoff = opts.tsval - synproxy->its;
 
index a86c7ae71881b1e65e998888c92749fe63fcf3c1..193db03540ad7c8dabd2f88be81fb5fe78eb8eab 100644 (file)
@@ -218,8 +218,10 @@ static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info)
 
        if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
                ipv4_sk_update_pmtu(skb, sk, info);
-       else if (type == ICMP_REDIRECT)
+       else if (type == ICMP_REDIRECT) {
                ipv4_sk_redirect(skb, sk);
+               return;
+       }
 
        /* Report error on raw socket, if:
           1. User requested ip_recverr.
@@ -387,7 +389,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
                iph->check   = 0;
                iph->tot_len = htons(length);
                if (!iph->id)
-                       ip_select_ident(iph, &rt->dst, NULL);
+                       ip_select_ident(skb, &rt->dst, NULL);
 
                iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
        }
index 4a22f3e715df930b9853cda07c4ec0f379553a9a..52f3c6b971d2def6854cf7d489022ad499ee0d24 100644 (file)
@@ -502,7 +502,9 @@ reset:
         * ACKs, wait for troubles.
         */
        if (crtt > tp->srtt) {
-               inet_csk(sk)->icsk_rto = crtt + max(crtt >> 2, tcp_rto_min(sk));
+               /* Set RTO like tcp_rtt_estimator(), but from cached RTT. */
+               crtt >>= 3;
+               inet_csk(sk)->icsk_rto = crtt + max(2 * crtt, tcp_rto_min(sk));
        } else if (tp->srtt == 0) {
                /* RFC6298: 5.7 We've failed to get a valid RTT sample from
                 * 3WHS. This is most likely due to retransmission,
index 7c83cb8bf1378022ba3a68c56403ef40801cd3ae..e6bb8256e59f3738280a022f250f6fefd621cb38 100644 (file)
@@ -895,8 +895,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
 
        skb_orphan(skb);
        skb->sk = sk;
-       skb->destructor = (sysctl_tcp_limit_output_bytes > 0) ?
-                         tcp_wfree : sock_wfree;
+       skb->destructor = tcp_wfree;
        atomic_add(skb->truesize, &sk->sk_wmem_alloc);
 
        /* Build TCP header and checksum it. */
@@ -1840,7 +1839,6 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
        while ((skb = tcp_send_head(sk))) {
                unsigned int limit;
 
-
                tso_segs = tcp_init_tso_segs(sk, skb, mss_now);
                BUG_ON(!tso_segs);
 
@@ -1869,13 +1867,20 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
                                break;
                }
 
-               /* TSQ : sk_wmem_alloc accounts skb truesize,
-                * including skb overhead. But thats OK.
+               /* TCP Small Queues :
+                * Control number of packets in qdisc/devices to two packets / or ~1 ms.
+                * This allows for :
+                *  - better RTT estimation and ACK scheduling
+                *  - faster recovery
+                *  - high rates
                 */
-               if (atomic_read(&sk->sk_wmem_alloc) >= sysctl_tcp_limit_output_bytes) {
+               limit = max(skb->truesize, sk->sk_pacing_rate >> 10);
+
+               if (atomic_read(&sk->sk_wmem_alloc) > limit) {
                        set_bit(TSQ_THROTTLED, &tp->tsq_flags);
                        break;
                }
+
                limit = mss_now;
                if (tso_segs > 1 && !tcp_urg_mode(tp))
                        limit = tcp_mss_split_point(sk, skb, mss_now,
index 74d2c95db57f3768d62ee450ed6bab64ca09b26d..0ca44df51ee94a2875427e5c9d3b1c77434f5f40 100644 (file)
@@ -658,7 +658,7 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
                break;
        case ICMP_REDIRECT:
                ipv4_sk_redirect(skb, sk);
-               break;
+               goto out;
        }
 
        /*
index eb1dd4d643f2f92d5a2385d0839d06a3424c545c..b5663c37f089ed0afe33115bcbfad2555b8d0f48 100644 (file)
@@ -117,7 +117,7 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
 
        top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
                0 : (XFRM_MODE_SKB_CB(skb)->frag_off & htons(IP_DF));
-       ip_select_ident(top_iph, dst->child, NULL);
+       ip_select_ident(skb, dst->child, NULL);
 
        top_iph->ttl = ip4_dst_hoplimit(dst->child);
 
index d6ff12617f36f9eabbf7c9744b3b8121a567c1bf..cd3fb301da38a970cd48302386428a8923f21c91 100644 (file)
@@ -1499,6 +1499,33 @@ static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
        return false;
 }
 
+/* Compares an address/prefix_len with addresses on device @dev.
+ * If one is found it returns true.
+ */
+bool ipv6_chk_custom_prefix(const struct in6_addr *addr,
+       const unsigned int prefix_len, struct net_device *dev)
+{
+       struct inet6_dev *idev;
+       struct inet6_ifaddr *ifa;
+       bool ret = false;
+
+       rcu_read_lock();
+       idev = __in6_dev_get(dev);
+       if (idev) {
+               read_lock_bh(&idev->lock);
+               list_for_each_entry(ifa, &idev->addr_list, if_list) {
+                       ret = ipv6_prefix_equal(addr, &ifa->addr, prefix_len);
+                       if (ret)
+                               break;
+               }
+               read_unlock_bh(&idev->lock);
+       }
+       rcu_read_unlock();
+
+       return ret;
+}
+EXPORT_SYMBOL(ipv6_chk_custom_prefix);
+
 int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev)
 {
        struct inet6_dev *idev;
@@ -2193,43 +2220,21 @@ ok:
                        else
                                stored_lft = 0;
                        if (!update_lft && !create && stored_lft) {
-                               if (valid_lft > MIN_VALID_LIFETIME ||
-                                   valid_lft > stored_lft)
-                                       update_lft = 1;
-                               else if (stored_lft <= MIN_VALID_LIFETIME) {
-                                       /* valid_lft <= stored_lft is always true */
-                                       /*
-                                        * RFC 4862 Section 5.5.3e:
-                                        * "Note that the preferred lifetime of
-                                        *  the corresponding address is always
-                                        *  reset to the Preferred Lifetime in
-                                        *  the received Prefix Information
-                                        *  option, regardless of whether the
-                                        *  valid lifetime is also reset or
-                                        *  ignored."
-                                        *
-                                        *  So if the preferred lifetime in
-                                        *  this advertisement is different
-                                        *  than what we have stored, but the
-                                        *  valid lifetime is invalid, just
-                                        *  reset prefered_lft.
-                                        *
-                                        *  We must set the valid lifetime
-                                        *  to the stored lifetime since we'll
-                                        *  be updating the timestamp below,
-                                        *  else we'll set it back to the
-                                        *  minimum.
-                                        */
-                                       if (prefered_lft != ifp->prefered_lft) {
-                                               valid_lft = stored_lft;
-                                               update_lft = 1;
-                                       }
-                               } else {
-                                       valid_lft = MIN_VALID_LIFETIME;
-                                       if (valid_lft < prefered_lft)
-                                               prefered_lft = valid_lft;
-                                       update_lft = 1;
-                               }
+                               const u32 minimum_lft = min(
+                                       stored_lft, (u32)MIN_VALID_LIFETIME);
+                               valid_lft = max(valid_lft, minimum_lft);
+
+                               /* RFC4862 Section 5.5.3e:
+                                * "Note that the preferred lifetime of the
+                                *  corresponding address is always reset to
+                                *  the Preferred Lifetime in the received
+                                *  Prefix Information option, regardless of
+                                *  whether the valid lifetime is also reset or
+                                *  ignored."
+                                *
+                                * So we should always update prefered_lft here.
+                                */
+                               update_lft = 1;
                        }
 
                        if (update_lft) {
index 6b26e9feafb98eb8d269f553cbf8339a3341526b..7bb5446b9d73c16a7f4096f2705ce60f997c7c2a 100644 (file)
@@ -618,7 +618,7 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb,
        struct ip6_tnl *tunnel = netdev_priv(dev);
        struct net_device *tdev;    /* Device to other host */
        struct ipv6hdr  *ipv6h;     /* Our new IP header */
-       unsigned int max_headroom /* The extra header space needed */
+       unsigned int max_headroom = 0; /* The extra header space needed */
        int    gre_hlen;
        struct ipv6_tel_txoption opt;
        int    mtu;
@@ -693,7 +693,7 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb,
 
        skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev)));
 
-       max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen + dst->header_len;
+       max_headroom += LL_RESERVED_SPACE(tdev) + gre_hlen + dst->header_len;
 
        if (skb_headroom(skb) < max_headroom || skb_shared(skb) ||
            (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
index 3a692d5291636571266c6e26293bc7054228f4e3..a54c45ce4a48f0d3a65f6c54ac77bb73a6a41280 100644 (file)
@@ -1015,6 +1015,8 @@ static inline int ip6_ufo_append_data(struct sock *sk,
         * udp datagram
         */
        if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) {
+               struct frag_hdr fhdr;
+
                skb = sock_alloc_send_skb(sk,
                        hh_len + fragheaderlen + transhdrlen + 20,
                        (flags & MSG_DONTWAIT), &err);
@@ -1036,12 +1038,6 @@ static inline int ip6_ufo_append_data(struct sock *sk,
                skb->protocol = htons(ETH_P_IPV6);
                skb->ip_summed = CHECKSUM_PARTIAL;
                skb->csum = 0;
-       }
-
-       err = skb_append_datato_frags(sk,skb, getfrag, from,
-                                     (length - transhdrlen));
-       if (!err) {
-               struct frag_hdr fhdr;
 
                /* Specify the length of each IPv6 datagram fragment.
                 * It has to be a multiple of 8.
@@ -1052,15 +1048,10 @@ static inline int ip6_ufo_append_data(struct sock *sk,
                ipv6_select_ident(&fhdr, rt);
                skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
                __skb_queue_tail(&sk->sk_write_queue, skb);
-
-               return 0;
        }
-       /* There is not enough support do UPD LSO,
-        * so follow normal path
-        */
-       kfree_skb(skb);
 
-       return err;
+       return skb_append_datato_frags(sk, skb, getfrag, from,
+                                      (length - transhdrlen));
 }
 
 static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src,
@@ -1227,27 +1218,27 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
         * --yoshfuji
         */
 
-       cork->length += length;
-       if (length > mtu) {
-               int proto = sk->sk_protocol;
-               if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){
-                       ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen);
-                       return -EMSGSIZE;
-               }
-
-               if (proto == IPPROTO_UDP &&
-                   (rt->dst.dev->features & NETIF_F_UFO)) {
+       if ((length > mtu) && dontfrag && (sk->sk_protocol == IPPROTO_UDP ||
+                                          sk->sk_protocol == IPPROTO_RAW)) {
+               ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen);
+               return -EMSGSIZE;
+       }
 
-                       err = ip6_ufo_append_data(sk, getfrag, from, length,
-                                                 hh_len, fragheaderlen,
-                                                 transhdrlen, mtu, flags, rt);
-                       if (err)
-                               goto error;
-                       return 0;
-               }
+       skb = skb_peek_tail(&sk->sk_write_queue);
+       cork->length += length;
+       if (((length > mtu) ||
+            (skb && skb_is_gso(skb))) &&
+           (sk->sk_protocol == IPPROTO_UDP) &&
+           (rt->dst.dev->features & NETIF_F_UFO)) {
+               err = ip6_ufo_append_data(sk, getfrag, from, length,
+                                         hh_len, fragheaderlen,
+                                         transhdrlen, mtu, flags, rt);
+               if (err)
+                       goto error;
+               return 0;
        }
 
-       if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
+       if (!skb)
                goto alloc_new_skb;
 
        while (length > 0) {
index 61355f7f4da5b4bb7bcc3c12030e09abe9fa9691..a791552e042212d866b2cd96c35e2f0b5d289ab5 100644 (file)
@@ -1656,9 +1656,9 @@ static int ip6_tnl_fill_info(struct sk_buff *skb, const struct net_device *dev)
 
        if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) ||
            nla_put(skb, IFLA_IPTUN_LOCAL, sizeof(struct in6_addr),
-                   &parm->raddr) ||
-           nla_put(skb, IFLA_IPTUN_REMOTE, sizeof(struct in6_addr),
                    &parm->laddr) ||
+           nla_put(skb, IFLA_IPTUN_REMOTE, sizeof(struct in6_addr),
+                   &parm->raddr) ||
            nla_put_u8(skb, IFLA_IPTUN_TTL, parm->hop_limit) ||
            nla_put_u8(skb, IFLA_IPTUN_ENCAP_LIMIT, parm->encap_limit) ||
            nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) ||
@@ -1731,8 +1731,6 @@ static void __net_exit ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n)
                }
        }
 
-       t = rtnl_dereference(ip6n->tnls_wc[0]);
-       unregister_netdevice_queue(t->dev, &list);
        unregister_netdevice_many(&list);
 }
 
@@ -1752,6 +1750,7 @@ static int __net_init ip6_tnl_init_net(struct net *net)
        if (!ip6n->fb_tnl_dev)
                goto err_alloc_dev;
        dev_net_set(ip6n->fb_tnl_dev, net);
+       ip6n->fb_tnl_dev->rtnl_link_ops = &ip6_link_ops;
        /* FB netdevice is special: we have one, and only one per netns.
         * Allowing to move it to another netns is clearly unsafe.
         */
index 096cd67b737c4b4eba2d42470d7a58e2e229153c..d18f9f903db62333983d3fad0e1ccb9298762c98 100644 (file)
@@ -2034,7 +2034,7 @@ static void mld_dad_timer_expire(unsigned long data)
                if (idev->mc_dad_count)
                        mld_dad_start_timer(idev, idev->mc_maxdelay);
        }
-       __in6_dev_put(idev);
+       in6_dev_put(idev);
 }
 
 static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
@@ -2379,7 +2379,7 @@ static void mld_gq_timer_expire(unsigned long data)
 
        idev->mc_gq_running = 0;
        mld_send_report(idev, NULL);
-       __in6_dev_put(idev);
+       in6_dev_put(idev);
 }
 
 static void mld_ifc_timer_expire(unsigned long data)
@@ -2392,7 +2392,7 @@ static void mld_ifc_timer_expire(unsigned long data)
                if (idev->mc_ifc_count)
                        mld_ifc_start_timer(idev, idev->mc_maxdelay);
        }
-       __in6_dev_put(idev);
+       in6_dev_put(idev);
 }
 
 static void mld_ifc_event(struct inet6_dev *idev)
index 19cfea8dbcaa0547c85e40f4217105ef46c7b683..2748b042da72eceb4002cf4183a781282c5e84d4 100644 (file)
@@ -282,7 +282,8 @@ synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par)
        if (th == NULL)
                return NF_DROP;
 
-       synproxy_parse_options(skb, par->thoff, th, &opts);
+       if (!synproxy_parse_options(skb, par->thoff, th, &opts))
+               return NF_DROP;
 
        if (th->syn && !(th->ack || th->fin || th->rst)) {
                /* Initial SYN from client */
@@ -372,7 +373,8 @@ static unsigned int ipv6_synproxy_hook(unsigned int hooknum,
 
                /* fall through */
        case TCP_CONNTRACK_SYN_SENT:
-               synproxy_parse_options(skb, thoff, th, &opts);
+               if (!synproxy_parse_options(skb, thoff, th, &opts))
+                       return NF_DROP;
 
                if (!th->syn && th->ack &&
                    CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) {
@@ -395,7 +397,9 @@ static unsigned int ipv6_synproxy_hook(unsigned int hooknum,
                if (!th->syn || !th->ack)
                        break;
 
-               synproxy_parse_options(skb, thoff, th, &opts);
+               if (!synproxy_parse_options(skb, thoff, th, &opts))
+                       return NF_DROP;
+
                if (opts.options & XT_SYNPROXY_OPT_TIMESTAMP)
                        synproxy->tsoff = opts.tsval - synproxy->its;
 
index 61aaf70f376e9eafee55cae3cb3b909916d0554e..2205e8eeeacfa2ff56980cbeb73b6d52c77089fe 100644 (file)
@@ -69,8 +69,8 @@ icmpv6_manip_pkt(struct sk_buff *skb,
        hdr = (struct icmp6hdr *)(skb->data + hdroff);
        l3proto->csum_update(skb, iphdroff, &hdr->icmp6_cksum,
                             tuple, maniptype);
-       if (hdr->icmp6_code == ICMPV6_ECHO_REQUEST ||
-           hdr->icmp6_code == ICMPV6_ECHO_REPLY) {
+       if (hdr->icmp6_type == ICMPV6_ECHO_REQUEST ||
+           hdr->icmp6_type == ICMPV6_ECHO_REPLY) {
                inet_proto_csum_replace2(&hdr->icmp6_cksum, skb,
                                         hdr->icmp6_identifier,
                                         tuple->src.u.icmp.id, 0);
index 58916bbb17284ed441611d0210c9514141ff9bf4..a4ed2416399ed52622b9c60460d411b9507e6d85 100644 (file)
@@ -335,8 +335,10 @@ static void rawv6_err(struct sock *sk, struct sk_buff *skb,
                ip6_sk_update_pmtu(skb, sk, info);
                harderr = (np->pmtudisc == IPV6_PMTUDISC_DO);
        }
-       if (type == NDISC_REDIRECT)
+       if (type == NDISC_REDIRECT) {
                ip6_sk_redirect(skb, sk);
+               return;
+       }
        if (np->recverr) {
                u8 *payload = skb->data;
                if (!inet->hdrincl)
index 7ee5cb96db348ab5c75946e77d3068c3c447ba17..19269453a8eaca1d34eefa648e401ccea7d829ac 100644 (file)
@@ -566,6 +566,70 @@ static inline bool is_spoofed_6rd(struct ip_tunnel *tunnel, const __be32 v4addr,
        return false;
 }
 
+/* Checks if an address matches an address on the tunnel interface.
+ * Used to detect the NAT of proto 41 packets and let them pass spoofing test.
+ * Long story:
+ * This function is called after we considered the packet as spoofed
+ * in is_spoofed_6rd.
+ * We may have a router that is doing NAT for proto 41 packets
+ * for an internal station. Destination a.a.a.a/PREFIX:bbbb:bbbb
+ * will be translated to n.n.n.n/PREFIX:bbbb:bbbb. And is_spoofed_6rd
+ * function will return true, dropping the packet.
+ * But, we can still check if is spoofed against the IP
+ * addresses associated with the interface.
+ */
+static bool only_dnatted(const struct ip_tunnel *tunnel,
+       const struct in6_addr *v6dst)
+{
+       int prefix_len;
+
+#ifdef CONFIG_IPV6_SIT_6RD
+       prefix_len = tunnel->ip6rd.prefixlen + 32
+               - tunnel->ip6rd.relay_prefixlen;
+#else
+       prefix_len = 48;
+#endif
+       return ipv6_chk_custom_prefix(v6dst, prefix_len, tunnel->dev);
+}
+
+/* Returns true if a packet is spoofed */
+static bool packet_is_spoofed(struct sk_buff *skb,
+                             const struct iphdr *iph,
+                             struct ip_tunnel *tunnel)
+{
+       const struct ipv6hdr *ipv6h;
+
+       if (tunnel->dev->priv_flags & IFF_ISATAP) {
+               if (!isatap_chksrc(skb, iph, tunnel))
+                       return true;
+
+               return false;
+       }
+
+       if (tunnel->dev->flags & IFF_POINTOPOINT)
+               return false;
+
+       ipv6h = ipv6_hdr(skb);
+
+       if (unlikely(is_spoofed_6rd(tunnel, iph->saddr, &ipv6h->saddr))) {
+               net_warn_ratelimited("Src spoofed %pI4/%pI6c -> %pI4/%pI6c\n",
+                                    &iph->saddr, &ipv6h->saddr,
+                                    &iph->daddr, &ipv6h->daddr);
+               return true;
+       }
+
+       if (likely(!is_spoofed_6rd(tunnel, iph->daddr, &ipv6h->daddr)))
+               return false;
+
+       if (only_dnatted(tunnel, &ipv6h->daddr))
+               return false;
+
+       net_warn_ratelimited("Dst spoofed %pI4/%pI6c -> %pI4/%pI6c\n",
+                            &iph->saddr, &ipv6h->saddr,
+                            &iph->daddr, &ipv6h->daddr);
+       return true;
+}
+
 static int ipip6_rcv(struct sk_buff *skb)
 {
        const struct iphdr *iph = ip_hdr(skb);
@@ -586,19 +650,9 @@ static int ipip6_rcv(struct sk_buff *skb)
                IPCB(skb)->flags = 0;
                skb->protocol = htons(ETH_P_IPV6);
 
-               if (tunnel->dev->priv_flags & IFF_ISATAP) {
-                       if (!isatap_chksrc(skb, iph, tunnel)) {
-                               tunnel->dev->stats.rx_errors++;
-                               goto out;
-                       }
-               } else if (!(tunnel->dev->flags&IFF_POINTOPOINT)) {
-                       if (is_spoofed_6rd(tunnel, iph->saddr,
-                                          &ipv6_hdr(skb)->saddr) ||
-                           is_spoofed_6rd(tunnel, iph->daddr,
-                                          &ipv6_hdr(skb)->daddr)) {
-                               tunnel->dev->stats.rx_errors++;
-                               goto out;
-                       }
+               if (packet_is_spoofed(skb, iph, tunnel)) {
+                       tunnel->dev->stats.rx_errors++;
+                       goto out;
                }
 
                __skb_tunnel_rx(skb, tunnel->dev, tunnel->net);
@@ -748,7 +802,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
                        neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr);
 
                if (neigh == NULL) {
-                       net_dbg_ratelimited("sit: nexthop == NULL\n");
+                       net_dbg_ratelimited("nexthop == NULL\n");
                        goto tx_error;
                }
 
@@ -777,7 +831,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
                        neigh = dst_neigh_lookup(skb_dst(skb), &iph6->daddr);
 
                if (neigh == NULL) {
-                       net_dbg_ratelimited("sit: nexthop == NULL\n");
+                       net_dbg_ratelimited("nexthop == NULL\n");
                        goto tx_error;
                }
 
@@ -1612,6 +1666,7 @@ static int __net_init sit_init_net(struct net *net)
                goto err_alloc_dev;
        }
        dev_net_set(sitn->fb_tunnel_dev, net);
+       sitn->fb_tunnel_dev->rtnl_link_ops = &sit_link_ops;
        /* FB netdevice is special: we have one, and only one per netns.
         * Allowing to move it to another netns is clearly unsafe.
         */
@@ -1646,7 +1701,6 @@ static void __net_exit sit_exit_net(struct net *net)
 
        rtnl_lock();
        sit_destroy_tunnels(sitn, &list);
-       unregister_netdevice_queue(sitn->fb_tunnel_dev, &list);
        unregister_netdevice_many(&list);
        rtnl_unlock();
 }
index f4058150262b111d316a423e1c9ddc7ee8bb29a0..72b7eaaf3ca0e3e6b7cad3edea8aa69e71cbe147 100644 (file)
@@ -525,8 +525,10 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
        if (type == ICMPV6_PKT_TOOBIG)
                ip6_sk_update_pmtu(skb, sk, info);
-       if (type == NDISC_REDIRECT)
+       if (type == NDISC_REDIRECT) {
                ip6_sk_redirect(skb, sk);
+               goto out;
+       }
 
        np = inet6_sk(sk);
 
index 54563ad8aeb1f02bbedd18959c8cf9cd77479942..355cc3b6fa4d3e4040bf9fb1578fc43c6c4f7b52 100644 (file)
@@ -154,6 +154,7 @@ static void lapb_t1timer_expiry(unsigned long param)
                        } else {
                                lapb->n2count++;
                                lapb_requeue_frames(lapb);
+                               lapb_kick(lapb);
                        }
                        break;
 
index f7713900798308557c134b00e9db3975e3697ecb..f2e30fb31e78efa405156ca99ba9aeaded3ea49c 100644 (file)
@@ -1052,7 +1052,7 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb,
         * Not an artificial restriction anymore, as we must prevent
         * possible loops created by swapping in setlist type of sets. */
        if (!(from->type->features == to->type->features &&
-             from->type->family == to->type->family))
+             from->family == to->family))
                return -IPSET_ERR_TYPE_MISMATCH;
 
        strncpy(from_name, from->name, IPSET_MAXNAMELEN);
@@ -1489,8 +1489,7 @@ ip_set_utest(struct sock *ctnl, struct sk_buff *skb,
        if (ret == -EAGAIN)
                ret = 1;
 
-       return (ret < 0 && ret != -ENOTEMPTY) ? ret :
-               ret > 0 ? 0 : -IPSET_ERR_EXIST;
+       return ret > 0 ? 0 : -IPSET_ERR_EXIST;
 }
 
 /* Get headed data of a set */
index 6fdf88ae2353b67be38c307fd8d4cb114594e624..dac156f819ac2f2fe25c876d800aadd2c47c0752 100644 (file)
@@ -116,12 +116,12 @@ ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
 {
        int protoff;
        u8 nexthdr;
-       __be16 frag_off;
+       __be16 frag_off = 0;
 
        nexthdr = ipv6_hdr(skb)->nexthdr;
        protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr,
                                   &frag_off);
-       if (protoff < 0)
+       if (protoff < 0 || (frag_off & htons(~0x7)) != 0)
                return false;
 
        return get_port(skb, nexthdr, protoff, src, port, proto);
index 57beb1762b2de5f77031d79cd54f5903d246c3f7..707bc520d629f311dd9978d2e0bf222719f71c82 100644 (file)
@@ -325,18 +325,22 @@ mtype_add_cidr(struct htype *h, u8 cidr, u8 nets_length)
 static void
 mtype_del_cidr(struct htype *h, u8 cidr, u8 nets_length)
 {
-       u8 i, j;
-
-       for (i = 0; i < nets_length - 1 && h->nets[i].cidr != cidr; i++)
-               ;
-       h->nets[i].nets--;
-
-       if (h->nets[i].nets != 0)
-               return;
-
-       for (j = i; j < nets_length - 1 && h->nets[j].nets; j++) {
-               h->nets[j].cidr = h->nets[j + 1].cidr;
-               h->nets[j].nets = h->nets[j + 1].nets;
+       u8 i, j, net_end = nets_length - 1;
+
+       for (i = 0; i < nets_length; i++) {
+               if (h->nets[i].cidr != cidr)
+                       continue;
+                if (h->nets[i].nets > 1 || i == net_end ||
+                    h->nets[i + 1].nets == 0) {
+                        h->nets[i].nets--;
+                        return;
+                }
+                for (j = i; j < net_end && h->nets[j].nets; j++) {
+                       h->nets[j].cidr = h->nets[j + 1].cidr;
+                       h->nets[j].nets = h->nets[j + 1].nets;
+                }
+                h->nets[j].nets = 0;
+                return;
        }
 }
 #endif
index c6a525373be4e24bb4de1d056095c5edfe3919c2..f15f3e28b9c338c6e72d3aa949d9d241c0e7cabe 100644 (file)
@@ -260,7 +260,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
                e.ip = htonl(ip);
                e.ip2 = htonl(ip2_from & ip_set_hostmask(e.cidr + 1));
                ret = adtfn(set, &e, &ext, &ext, flags);
-               return ip_set_enomatch(ret, flags, adt) ? 1 :
+               return ip_set_enomatch(ret, flags, adt, set) ? -ret :
                       ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
@@ -544,7 +544,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
 
        if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
                ret = adtfn(set, &e, &ext, &ext, flags);
-               return ip_set_enomatch(ret, flags, adt) ? 1 :
+               return ip_set_enomatch(ret, flags, adt, set) ? -ret :
                       ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
index da740ceb56aefc8db240d83d74daf68a631ec975..223e9f546d0fa3e414b7a53a839b56d6835093bb 100644 (file)
@@ -199,7 +199,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
        if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
                e.ip = htonl(ip & ip_set_hostmask(e.cidr));
                ret = adtfn(set, &e, &ext, &ext, flags);
-               return ip_set_enomatch(ret, flags, adt) ? 1 :
+               return ip_set_enomatch(ret, flags, adt, set) ? -ret:
                       ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
@@ -396,7 +396,7 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
 
        ret = adtfn(set, &e, &ext, &ext, flags);
 
-       return ip_set_enomatch(ret, flags, adt) ? 1 :
+       return ip_set_enomatch(ret, flags, adt, set) ? -ret :
               ip_set_eexist(ret, flags) ? 0 : ret;
 }
 
index 84ae6f6ce624665f9d2cc27c07efe9033412f132..7d798d5d5cd30a66de3d6fade0b4110eeba583f7 100644 (file)
@@ -368,7 +368,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
        if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
                e.ip = htonl(ip & ip_set_hostmask(e.cidr));
                ret = adtfn(set, &e, &ext, &ext, flags);
-               return ip_set_enomatch(ret, flags, adt) ? 1 :
+               return ip_set_enomatch(ret, flags, adt, set) ? -ret :
                       ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
@@ -634,7 +634,7 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
 
        ret = adtfn(set, &e, &ext, &ext, flags);
 
-       return ip_set_enomatch(ret, flags, adt) ? 1 :
+       return ip_set_enomatch(ret, flags, adt, set) ? -ret :
               ip_set_eexist(ret, flags) ? 0 : ret;
 }
 
index 9a0869853be565ca09a7e6c54c9cd205229dd3bf..09d6690bee6fd33891c4a00bbbb909f2bbf7731b 100644 (file)
@@ -244,7 +244,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
        if (adt == IPSET_TEST || !(with_ports || tb[IPSET_ATTR_IP_TO])) {
                e.ip = htonl(ip & ip_set_hostmask(e.cidr + 1));
                ret = adtfn(set, &e, &ext, &ext, flags);
-               return ip_set_enomatch(ret, flags, adt) ? 1 :
+               return ip_set_enomatch(ret, flags, adt, set) ? -ret :
                       ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
@@ -489,7 +489,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
 
        if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
                ret = adtfn(set, &e, &ext, &ext, flags);
-               return ip_set_enomatch(ret, flags, adt) ? 1 :
+               return ip_set_enomatch(ret, flags, adt, set) ? -ret :
                       ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
index 4f69e83ff836b0ec415342772055a58a52c25fc4..74fd00c272100d5271533689abf074c5f9e8c454 100644 (file)
@@ -116,6 +116,7 @@ ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
 
        if (dest && (dest->flags & IP_VS_DEST_F_AVAILABLE)) {
                struct ip_vs_cpu_stats *s;
+               struct ip_vs_service *svc;
 
                s = this_cpu_ptr(dest->stats.cpustats);
                s->ustats.inpkts++;
@@ -123,11 +124,14 @@ ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
                s->ustats.inbytes += skb->len;
                u64_stats_update_end(&s->syncp);
 
-               s = this_cpu_ptr(dest->svc->stats.cpustats);
+               rcu_read_lock();
+               svc = rcu_dereference(dest->svc);
+               s = this_cpu_ptr(svc->stats.cpustats);
                s->ustats.inpkts++;
                u64_stats_update_begin(&s->syncp);
                s->ustats.inbytes += skb->len;
                u64_stats_update_end(&s->syncp);
+               rcu_read_unlock();
 
                s = this_cpu_ptr(ipvs->tot_stats.cpustats);
                s->ustats.inpkts++;
@@ -146,6 +150,7 @@ ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
 
        if (dest && (dest->flags & IP_VS_DEST_F_AVAILABLE)) {
                struct ip_vs_cpu_stats *s;
+               struct ip_vs_service *svc;
 
                s = this_cpu_ptr(dest->stats.cpustats);
                s->ustats.outpkts++;
@@ -153,11 +158,14 @@ ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
                s->ustats.outbytes += skb->len;
                u64_stats_update_end(&s->syncp);
 
-               s = this_cpu_ptr(dest->svc->stats.cpustats);
+               rcu_read_lock();
+               svc = rcu_dereference(dest->svc);
+               s = this_cpu_ptr(svc->stats.cpustats);
                s->ustats.outpkts++;
                u64_stats_update_begin(&s->syncp);
                s->ustats.outbytes += skb->len;
                u64_stats_update_end(&s->syncp);
+               rcu_read_unlock();
 
                s = this_cpu_ptr(ipvs->tot_stats.cpustats);
                s->ustats.outpkts++;
index c8148e48738657d63810a1dade924267dc032d01..a3df9bddc4f76251a8722792d8e9f15478546ac1 100644 (file)
@@ -460,7 +460,7 @@ static inline void
 __ip_vs_bind_svc(struct ip_vs_dest *dest, struct ip_vs_service *svc)
 {
        atomic_inc(&svc->refcnt);
-       dest->svc = svc;
+       rcu_assign_pointer(dest->svc, svc);
 }
 
 static void ip_vs_service_free(struct ip_vs_service *svc)
@@ -470,18 +470,25 @@ static void ip_vs_service_free(struct ip_vs_service *svc)
        kfree(svc);
 }
 
-static void
-__ip_vs_unbind_svc(struct ip_vs_dest *dest)
+static void ip_vs_service_rcu_free(struct rcu_head *head)
 {
-       struct ip_vs_service *svc = dest->svc;
+       struct ip_vs_service *svc;
+
+       svc = container_of(head, struct ip_vs_service, rcu_head);
+       ip_vs_service_free(svc);
+}
 
-       dest->svc = NULL;
+static void __ip_vs_svc_put(struct ip_vs_service *svc, bool do_delay)
+{
        if (atomic_dec_and_test(&svc->refcnt)) {
                IP_VS_DBG_BUF(3, "Removing service %u/%s:%u\n",
                              svc->fwmark,
                              IP_VS_DBG_ADDR(svc->af, &svc->addr),
                              ntohs(svc->port));
-               ip_vs_service_free(svc);
+               if (do_delay)
+                       call_rcu(&svc->rcu_head, ip_vs_service_rcu_free);
+               else
+                       ip_vs_service_free(svc);
        }
 }
 
@@ -667,11 +674,6 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr,
                              IP_VS_DBG_ADDR(svc->af, &dest->addr),
                              ntohs(dest->port),
                              atomic_read(&dest->refcnt));
-               /* We can not reuse dest while in grace period
-                * because conns still can use dest->svc
-                */
-               if (test_bit(IP_VS_DEST_STATE_REMOVING, &dest->state))
-                       continue;
                if (dest->af == svc->af &&
                    ip_vs_addr_equal(svc->af, &dest->addr, daddr) &&
                    dest->port == dport &&
@@ -697,8 +699,10 @@ out:
 
 static void ip_vs_dest_free(struct ip_vs_dest *dest)
 {
+       struct ip_vs_service *svc = rcu_dereference_protected(dest->svc, 1);
+
        __ip_vs_dst_cache_reset(dest);
-       __ip_vs_unbind_svc(dest);
+       __ip_vs_svc_put(svc, false);
        free_percpu(dest->stats.cpustats);
        kfree(dest);
 }
@@ -771,6 +775,7 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
                    struct ip_vs_dest_user_kern *udest, int add)
 {
        struct netns_ipvs *ipvs = net_ipvs(svc->net);
+       struct ip_vs_service *old_svc;
        struct ip_vs_scheduler *sched;
        int conn_flags;
 
@@ -792,13 +797,14 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
        atomic_set(&dest->conn_flags, conn_flags);
 
        /* bind the service */
-       if (!dest->svc) {
+       old_svc = rcu_dereference_protected(dest->svc, 1);
+       if (!old_svc) {
                __ip_vs_bind_svc(dest, svc);
        } else {
-               if (dest->svc != svc) {
-                       __ip_vs_unbind_svc(dest);
+               if (old_svc != svc) {
                        ip_vs_zero_stats(&dest->stats);
                        __ip_vs_bind_svc(dest, svc);
+                       __ip_vs_svc_put(old_svc, true);
                }
        }
 
@@ -998,16 +1004,6 @@ ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
        return 0;
 }
 
-static void ip_vs_dest_wait_readers(struct rcu_head *head)
-{
-       struct ip_vs_dest *dest = container_of(head, struct ip_vs_dest,
-                                              rcu_head);
-
-       /* End of grace period after unlinking */
-       clear_bit(IP_VS_DEST_STATE_REMOVING, &dest->state);
-}
-
-
 /*
  *     Delete a destination (must be already unlinked from the service)
  */
@@ -1023,20 +1019,16 @@ static void __ip_vs_del_dest(struct net *net, struct ip_vs_dest *dest,
         */
        ip_vs_rs_unhash(dest);
 
-       if (!cleanup) {
-               set_bit(IP_VS_DEST_STATE_REMOVING, &dest->state);
-               call_rcu(&dest->rcu_head, ip_vs_dest_wait_readers);
-       }
-
        spin_lock_bh(&ipvs->dest_trash_lock);
        IP_VS_DBG_BUF(3, "Moving dest %s:%u into trash, dest->refcnt=%d\n",
                      IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port),
                      atomic_read(&dest->refcnt));
        if (list_empty(&ipvs->dest_trash) && !cleanup)
                mod_timer(&ipvs->dest_trash_timer,
-                         jiffies + IP_VS_DEST_TRASH_PERIOD);
+                         jiffies + (IP_VS_DEST_TRASH_PERIOD >> 1));
        /* dest lives in trash without reference */
        list_add(&dest->t_list, &ipvs->dest_trash);
+       dest->idle_start = 0;
        spin_unlock_bh(&ipvs->dest_trash_lock);
        ip_vs_dest_put(dest);
 }
@@ -1108,24 +1100,30 @@ static void ip_vs_dest_trash_expire(unsigned long data)
        struct net *net = (struct net *) data;
        struct netns_ipvs *ipvs = net_ipvs(net);
        struct ip_vs_dest *dest, *next;
+       unsigned long now = jiffies;
 
        spin_lock(&ipvs->dest_trash_lock);
        list_for_each_entry_safe(dest, next, &ipvs->dest_trash, t_list) {
-               /* Skip if dest is in grace period */
-               if (test_bit(IP_VS_DEST_STATE_REMOVING, &dest->state))
-                       continue;
                if (atomic_read(&dest->refcnt) > 0)
                        continue;
+               if (dest->idle_start) {
+                       if (time_before(now, dest->idle_start +
+                                            IP_VS_DEST_TRASH_PERIOD))
+                               continue;
+               } else {
+                       dest->idle_start = max(1UL, now);
+                       continue;
+               }
                IP_VS_DBG_BUF(3, "Removing destination %u/%s:%u from trash\n",
                              dest->vfwmark,
-                             IP_VS_DBG_ADDR(dest->svc->af, &dest->addr),
+                             IP_VS_DBG_ADDR(dest->af, &dest->addr),
                              ntohs(dest->port));
                list_del(&dest->t_list);
                ip_vs_dest_free(dest);
        }
        if (!list_empty(&ipvs->dest_trash))
                mod_timer(&ipvs->dest_trash_timer,
-                         jiffies + IP_VS_DEST_TRASH_PERIOD);
+                         jiffies + (IP_VS_DEST_TRASH_PERIOD >> 1));
        spin_unlock(&ipvs->dest_trash_lock);
 }
 
@@ -1320,14 +1318,6 @@ out:
        return ret;
 }
 
-static void ip_vs_service_rcu_free(struct rcu_head *head)
-{
-       struct ip_vs_service *svc;
-
-       svc = container_of(head, struct ip_vs_service, rcu_head);
-       ip_vs_service_free(svc);
-}
-
 /*
  *     Delete a service from the service list
  *     - The service must be unlinked, unlocked and not referenced!
@@ -1376,13 +1366,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup)
        /*
         *    Free the service if nobody refers to it
         */
-       if (atomic_dec_and_test(&svc->refcnt)) {
-               IP_VS_DBG_BUF(3, "Removing service %u/%s:%u\n",
-                             svc->fwmark,
-                             IP_VS_DBG_ADDR(svc->af, &svc->addr),
-                             ntohs(svc->port));
-               call_rcu(&svc->rcu_head, ip_vs_service_rcu_free);
-       }
+       __ip_vs_svc_put(svc, true);
 
        /* decrease the module use count */
        ip_vs_use_count_dec();
index 6bee6d0c73a52e93e1413162b4db971340fa3312..1425e9a924c4f64429637bc49cbde204b0bb1921 100644 (file)
@@ -59,12 +59,13 @@ static void ip_vs_read_cpu_stats(struct ip_vs_stats_user *sum,
                                 struct ip_vs_cpu_stats __percpu *stats)
 {
        int i;
+       bool add = false;
 
        for_each_possible_cpu(i) {
                struct ip_vs_cpu_stats *s = per_cpu_ptr(stats, i);
                unsigned int start;
                __u64 inbytes, outbytes;
-               if (i) {
+               if (add) {
                        sum->conns += s->ustats.conns;
                        sum->inpkts += s->ustats.inpkts;
                        sum->outpkts += s->ustats.outpkts;
@@ -76,6 +77,7 @@ static void ip_vs_read_cpu_stats(struct ip_vs_stats_user *sum,
                        sum->inbytes += inbytes;
                        sum->outbytes += outbytes;
                } else {
+                       add = true;
                        sum->conns = s->ustats.conns;
                        sum->inpkts = s->ustats.inpkts;
                        sum->outpkts = s->ustats.outpkts;
index 1383b0eadc0e777d5ff6dbce2a2ded451a3ae296..eff13c94498e068173c66b6a481a6264d038ffea 100644 (file)
@@ -93,7 +93,7 @@ struct ip_vs_lblc_entry {
        struct hlist_node       list;
        int                     af;             /* address family */
        union nf_inet_addr      addr;           /* destination IP address */
-       struct ip_vs_dest __rcu *dest;          /* real server (cache) */
+       struct ip_vs_dest       *dest;          /* real server (cache) */
        unsigned long           lastuse;        /* last used time */
        struct rcu_head         rcu_head;
 };
@@ -130,20 +130,21 @@ static struct ctl_table vs_vars_table[] = {
 };
 #endif
 
-static inline void ip_vs_lblc_free(struct ip_vs_lblc_entry *en)
+static void ip_vs_lblc_rcu_free(struct rcu_head *head)
 {
-       struct ip_vs_dest *dest;
+       struct ip_vs_lblc_entry *en = container_of(head,
+                                                  struct ip_vs_lblc_entry,
+                                                  rcu_head);
 
-       hlist_del_rcu(&en->list);
-       /*
-        * We don't kfree dest because it is referred either by its service
-        * or the trash dest list.
-        */
-       dest = rcu_dereference_protected(en->dest, 1);
-       ip_vs_dest_put(dest);
-       kfree_rcu(en, rcu_head);
+       ip_vs_dest_put(en->dest);
+       kfree(en);
 }
 
+static inline void ip_vs_lblc_del(struct ip_vs_lblc_entry *en)
+{
+       hlist_del_rcu(&en->list);
+       call_rcu(&en->rcu_head, ip_vs_lblc_rcu_free);
+}
 
 /*
  *     Returns hash value for IPVS LBLC entry
@@ -203,30 +204,23 @@ ip_vs_lblc_new(struct ip_vs_lblc_table *tbl, const union nf_inet_addr *daddr,
        struct ip_vs_lblc_entry *en;
 
        en = ip_vs_lblc_get(dest->af, tbl, daddr);
-       if (!en) {
-               en = kmalloc(sizeof(*en), GFP_ATOMIC);
-               if (!en)
-                       return NULL;
-
-               en->af = dest->af;
-               ip_vs_addr_copy(dest->af, &en->addr, daddr);
-               en->lastuse = jiffies;
+       if (en) {
+               if (en->dest == dest)
+                       return en;
+               ip_vs_lblc_del(en);
+       }
+       en = kmalloc(sizeof(*en), GFP_ATOMIC);
+       if (!en)
+               return NULL;
 
-               ip_vs_dest_hold(dest);
-               RCU_INIT_POINTER(en->dest, dest);
+       en->af = dest->af;
+       ip_vs_addr_copy(dest->af, &en->addr, daddr);
+       en->lastuse = jiffies;
 
-               ip_vs_lblc_hash(tbl, en);
-       } else {
-               struct ip_vs_dest *old_dest;
+       ip_vs_dest_hold(dest);
+       en->dest = dest;
 
-               old_dest = rcu_dereference_protected(en->dest, 1);
-               if (old_dest != dest) {
-                       ip_vs_dest_put(old_dest);
-                       ip_vs_dest_hold(dest);
-                       /* No ordering constraints for refcnt */
-                       RCU_INIT_POINTER(en->dest, dest);
-               }
-       }
+       ip_vs_lblc_hash(tbl, en);
 
        return en;
 }
@@ -246,7 +240,7 @@ static void ip_vs_lblc_flush(struct ip_vs_service *svc)
        tbl->dead = 1;
        for (i=0; i<IP_VS_LBLC_TAB_SIZE; i++) {
                hlist_for_each_entry_safe(en, next, &tbl->bucket[i], list) {
-                       ip_vs_lblc_free(en);
+                       ip_vs_lblc_del(en);
                        atomic_dec(&tbl->entries);
                }
        }
@@ -281,7 +275,7 @@ static inline void ip_vs_lblc_full_check(struct ip_vs_service *svc)
                                        sysctl_lblc_expiration(svc)))
                                continue;
 
-                       ip_vs_lblc_free(en);
+                       ip_vs_lblc_del(en);
                        atomic_dec(&tbl->entries);
                }
                spin_unlock(&svc->sched_lock);
@@ -335,7 +329,7 @@ static void ip_vs_lblc_check_expire(unsigned long data)
                        if (time_before(now, en->lastuse + ENTRY_TIMEOUT))
                                continue;
 
-                       ip_vs_lblc_free(en);
+                       ip_vs_lblc_del(en);
                        atomic_dec(&tbl->entries);
                        goal--;
                }
@@ -443,8 +437,8 @@ __ip_vs_lblc_schedule(struct ip_vs_service *svc)
                        continue;
 
                doh = ip_vs_dest_conn_overhead(dest);
-               if (loh * atomic_read(&dest->weight) >
-                   doh * atomic_read(&least->weight)) {
+               if ((__s64)loh * atomic_read(&dest->weight) >
+                   (__s64)doh * atomic_read(&least->weight)) {
                        least = dest;
                        loh = doh;
                }
@@ -511,7 +505,7 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
                 * free up entries from the trash at any time.
                 */
 
-               dest = rcu_dereference(en->dest);
+               dest = en->dest;
                if ((dest->flags & IP_VS_DEST_F_AVAILABLE) &&
                    atomic_read(&dest->weight) > 0 && !is_overloaded(dest, svc))
                        goto out;
@@ -631,7 +625,7 @@ static void __exit ip_vs_lblc_cleanup(void)
 {
        unregister_ip_vs_scheduler(&ip_vs_lblc_scheduler);
        unregister_pernet_subsys(&ip_vs_lblc_ops);
-       synchronize_rcu();
+       rcu_barrier();
 }
 
 
index 5199448697f64fcf0da0e35dbc38903477a92861..0b8550089a2e580e7feba0723117f1c849048a39 100644 (file)
@@ -89,7 +89,7 @@
  */
 struct ip_vs_dest_set_elem {
        struct list_head        list;          /* list link */
-       struct ip_vs_dest __rcu *dest;         /* destination server */
+       struct ip_vs_dest       *dest;          /* destination server */
        struct rcu_head         rcu_head;
 };
 
@@ -107,11 +107,7 @@ static void ip_vs_dest_set_insert(struct ip_vs_dest_set *set,
 
        if (check) {
                list_for_each_entry(e, &set->list, list) {
-                       struct ip_vs_dest *d;
-
-                       d = rcu_dereference_protected(e->dest, 1);
-                       if (d == dest)
-                               /* already existed */
+                       if (e->dest == dest)
                                return;
                }
        }
@@ -121,7 +117,7 @@ static void ip_vs_dest_set_insert(struct ip_vs_dest_set *set,
                return;
 
        ip_vs_dest_hold(dest);
-       RCU_INIT_POINTER(e->dest, dest);
+       e->dest = dest;
 
        list_add_rcu(&e->list, &set->list);
        atomic_inc(&set->size);
@@ -129,22 +125,27 @@ static void ip_vs_dest_set_insert(struct ip_vs_dest_set *set,
        set->lastmod = jiffies;
 }
 
+static void ip_vs_lblcr_elem_rcu_free(struct rcu_head *head)
+{
+       struct ip_vs_dest_set_elem *e;
+
+       e = container_of(head, struct ip_vs_dest_set_elem, rcu_head);
+       ip_vs_dest_put(e->dest);
+       kfree(e);
+}
+
 static void
 ip_vs_dest_set_erase(struct ip_vs_dest_set *set, struct ip_vs_dest *dest)
 {
        struct ip_vs_dest_set_elem *e;
 
        list_for_each_entry(e, &set->list, list) {
-               struct ip_vs_dest *d;
-
-               d = rcu_dereference_protected(e->dest, 1);
-               if (d == dest) {
+               if (e->dest == dest) {
                        /* HIT */
                        atomic_dec(&set->size);
                        set->lastmod = jiffies;
-                       ip_vs_dest_put(dest);
                        list_del_rcu(&e->list);
-                       kfree_rcu(e, rcu_head);
+                       call_rcu(&e->rcu_head, ip_vs_lblcr_elem_rcu_free);
                        break;
                }
        }
@@ -155,16 +156,8 @@ static void ip_vs_dest_set_eraseall(struct ip_vs_dest_set *set)
        struct ip_vs_dest_set_elem *e, *ep;
 
        list_for_each_entry_safe(e, ep, &set->list, list) {
-               struct ip_vs_dest *d;
-
-               d = rcu_dereference_protected(e->dest, 1);
-               /*
-                * We don't kfree dest because it is referred either
-                * by its service or by the trash dest list.
-                */
-               ip_vs_dest_put(d);
                list_del_rcu(&e->list);
-               kfree_rcu(e, rcu_head);
+               call_rcu(&e->rcu_head, ip_vs_lblcr_elem_rcu_free);
        }
 }
 
@@ -175,12 +168,9 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set)
        struct ip_vs_dest *dest, *least;
        int loh, doh;
 
-       if (set == NULL)
-               return NULL;
-
        /* select the first destination server, whose weight > 0 */
        list_for_each_entry_rcu(e, &set->list, list) {
-               least = rcu_dereference(e->dest);
+               least = e->dest;
                if (least->flags & IP_VS_DEST_F_OVERLOAD)
                        continue;
 
@@ -195,13 +185,13 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set)
        /* find the destination with the weighted least load */
   nextstage:
        list_for_each_entry_continue_rcu(e, &set->list, list) {
-               dest = rcu_dereference(e->dest);
+               dest = e->dest;
                if (dest->flags & IP_VS_DEST_F_OVERLOAD)
                        continue;
 
                doh = ip_vs_dest_conn_overhead(dest);
-               if ((loh * atomic_read(&dest->weight) >
-                    doh * atomic_read(&least->weight))
+               if (((__s64)loh * atomic_read(&dest->weight) >
+                    (__s64)doh * atomic_read(&least->weight))
                    && (dest->flags & IP_VS_DEST_F_AVAILABLE)) {
                        least = dest;
                        loh = doh;
@@ -232,7 +222,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set)
 
        /* select the first destination server, whose weight > 0 */
        list_for_each_entry(e, &set->list, list) {
-               most = rcu_dereference_protected(e->dest, 1);
+               most = e->dest;
                if (atomic_read(&most->weight) > 0) {
                        moh = ip_vs_dest_conn_overhead(most);
                        goto nextstage;
@@ -243,11 +233,11 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set)
        /* find the destination with the weighted most load */
   nextstage:
        list_for_each_entry_continue(e, &set->list, list) {
-               dest = rcu_dereference_protected(e->dest, 1);
+               dest = e->dest;
                doh = ip_vs_dest_conn_overhead(dest);
                /* moh/mw < doh/dw ==> moh*dw < doh*mw, where mw,dw>0 */
-               if ((moh * atomic_read(&dest->weight) <
-                    doh * atomic_read(&most->weight))
+               if (((__s64)moh * atomic_read(&dest->weight) <
+                    (__s64)doh * atomic_read(&most->weight))
                    && (atomic_read(&dest->weight) > 0)) {
                        most = dest;
                        moh = doh;
@@ -611,8 +601,8 @@ __ip_vs_lblcr_schedule(struct ip_vs_service *svc)
                        continue;
 
                doh = ip_vs_dest_conn_overhead(dest);
-               if (loh * atomic_read(&dest->weight) >
-                   doh * atomic_read(&least->weight)) {
+               if ((__s64)loh * atomic_read(&dest->weight) >
+                   (__s64)doh * atomic_read(&least->weight)) {
                        least = dest;
                        loh = doh;
                }
@@ -819,7 +809,7 @@ static void __exit ip_vs_lblcr_cleanup(void)
 {
        unregister_ip_vs_scheduler(&ip_vs_lblcr_scheduler);
        unregister_pernet_subsys(&ip_vs_lblcr_ops);
-       synchronize_rcu();
+       rcu_barrier();
 }
 
 
index d8d9860934fee1e7f59505eeefa094307b2d58c3..961a6de9bb29035458945185f488a5fc1209ba00 100644 (file)
@@ -40,7 +40,7 @@
 #include <net/ip_vs.h>
 
 
-static inline unsigned int
+static inline int
 ip_vs_nq_dest_overhead(struct ip_vs_dest *dest)
 {
        /*
@@ -59,7 +59,7 @@ ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
                  struct ip_vs_iphdr *iph)
 {
        struct ip_vs_dest *dest, *least = NULL;
-       unsigned int loh = 0, doh;
+       int loh = 0, doh;
 
        IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
 
@@ -92,8 +92,8 @@ ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
                }
 
                if (!least ||
-                   (loh * atomic_read(&dest->weight) >
-                    doh * atomic_read(&least->weight))) {
+                   ((__s64)loh * atomic_read(&dest->weight) >
+                    (__s64)doh * atomic_read(&least->weight))) {
                        least = dest;
                        loh = doh;
                }
index a5284cc3d88279923b6a28b1f8a8f87bfc2a6a0f..e446b9fa7424c6382cb65433447f3febe2b17eeb 100644 (file)
@@ -44,7 +44,7 @@
 #include <net/ip_vs.h>
 
 
-static inline unsigned int
+static inline int
 ip_vs_sed_dest_overhead(struct ip_vs_dest *dest)
 {
        /*
@@ -63,7 +63,7 @@ ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
                   struct ip_vs_iphdr *iph)
 {
        struct ip_vs_dest *dest, *least;
-       unsigned int loh, doh;
+       int loh, doh;
 
        IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
 
@@ -99,8 +99,8 @@ ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
                if (dest->flags & IP_VS_DEST_F_OVERLOAD)
                        continue;
                doh = ip_vs_sed_dest_overhead(dest);
-               if (loh * atomic_read(&dest->weight) >
-                   doh * atomic_read(&least->weight)) {
+               if ((__s64)loh * atomic_read(&dest->weight) >
+                   (__s64)doh * atomic_read(&least->weight)) {
                        least = dest;
                        loh = doh;
                }
index 6dc1fa1288409067de8a19f53a32e174caa9adc9..b5b4650d50a9180f211e6cce82e3393ece2fc11c 100644 (file)
@@ -35,7 +35,7 @@ ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
                   struct ip_vs_iphdr *iph)
 {
        struct ip_vs_dest *dest, *least;
-       unsigned int loh, doh;
+       int loh, doh;
 
        IP_VS_DBG(6, "ip_vs_wlc_schedule(): Scheduling...\n");
 
@@ -71,8 +71,8 @@ ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
                if (dest->flags & IP_VS_DEST_F_OVERLOAD)
                        continue;
                doh = ip_vs_dest_conn_overhead(dest);
-               if (loh * atomic_read(&dest->weight) >
-                   doh * atomic_read(&least->weight)) {
+               if ((__s64)loh * atomic_read(&dest->weight) >
+                   (__s64)doh * atomic_read(&least->weight)) {
                        least = dest;
                        loh = doh;
                }
index b75ff6429a04e25d4ba8e6368173ab84a342751c..c47444e4cf8ccc9977fa0622689b4fb55799ff4b 100644 (file)
@@ -883,7 +883,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
        iph->daddr              =       cp->daddr.ip;
        iph->saddr              =       saddr;
        iph->ttl                =       old_iph->ttl;
-       ip_select_ident(iph, &rt->dst, NULL);
+       ip_select_ident(skb, &rt->dst, NULL);
 
        /* Another hack: avoid icmp_send in ip_fragment */
        skb->local_df = 1;
index 6fd967c6278c86fbc81ad232035891656750330a..cdf4567ba9b330929aec53eb1c75d57a7047106e 100644 (file)
@@ -24,7 +24,7 @@
 int synproxy_net_id;
 EXPORT_SYMBOL_GPL(synproxy_net_id);
 
-void
+bool
 synproxy_parse_options(const struct sk_buff *skb, unsigned int doff,
                       const struct tcphdr *th, struct synproxy_options *opts)
 {
@@ -32,7 +32,8 @@ synproxy_parse_options(const struct sk_buff *skb, unsigned int doff,
        u8 buf[40], *ptr;
 
        ptr = skb_header_pointer(skb, doff + sizeof(*th), length, buf);
-       BUG_ON(ptr == NULL);
+       if (ptr == NULL)
+               return false;
 
        opts->options = 0;
        while (length > 0) {
@@ -41,16 +42,16 @@ synproxy_parse_options(const struct sk_buff *skb, unsigned int doff,
 
                switch (opcode) {
                case TCPOPT_EOL:
-                       return;
+                       return true;
                case TCPOPT_NOP:
                        length--;
                        continue;
                default:
                        opsize = *ptr++;
                        if (opsize < 2)
-                               return;
+                               return true;
                        if (opsize > length)
-                               return;
+                               return true;
 
                        switch (opcode) {
                        case TCPOPT_MSS:
@@ -84,6 +85,7 @@ synproxy_parse_options(const struct sk_buff *skb, unsigned int doff,
                        length -= opsize;
                }
        }
+       return true;
 }
 EXPORT_SYMBOL_GPL(synproxy_parse_options);
 
index 95a98c8c1da65be10ea5499aba6291cdf8319fed..ae2e5c11d01ac9887c5158d0084f193c624373ef 100644 (file)
@@ -1009,7 +1009,7 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
                        verdict = NF_DROP;
 
                if (ct)
-                       nfqnl_ct_seq_adjust(skb, ct, ctinfo, diff);
+                       nfqnl_ct_seq_adjust(entry->skb, ct, ctinfo, diff);
        }
 
        if (nfqa[NFQA_MARK])
index 32ad015ee8ce4a9c5b967c22dd90631881f2362b..a2fef8b10b960c15d29556b7dc832737c848b3b6 100644 (file)
@@ -285,7 +285,7 @@ static struct fq_flow *fq_classify(struct sk_buff *skb, struct fq_sched_data *q)
 
 
 /* remove one skb from head of flow queue */
-static struct sk_buff *fq_dequeue_head(struct fq_flow *flow)
+static struct sk_buff *fq_dequeue_head(struct Qdisc *sch, struct fq_flow *flow)
 {
        struct sk_buff *skb = flow->head;
 
@@ -293,6 +293,8 @@ static struct sk_buff *fq_dequeue_head(struct fq_flow *flow)
                flow->head = skb->next;
                skb->next = NULL;
                flow->qlen--;
+               sch->qstats.backlog -= qdisc_pkt_len(skb);
+               sch->q.qlen--;
        }
        return skb;
 }
@@ -418,8 +420,9 @@ static struct sk_buff *fq_dequeue(struct Qdisc *sch)
        struct fq_flow_head *head;
        struct sk_buff *skb;
        struct fq_flow *f;
+       u32 rate;
 
-       skb = fq_dequeue_head(&q->internal);
+       skb = fq_dequeue_head(sch, &q->internal);
        if (skb)
                goto out;
        fq_check_throttled(q, now);
@@ -449,7 +452,7 @@ begin:
                goto begin;
        }
 
-       skb = fq_dequeue_head(f);
+       skb = fq_dequeue_head(sch, f);
        if (!skb) {
                head->first = f->next;
                /* force a pass through old_flows to prevent starvation */
@@ -466,43 +469,74 @@ begin:
        f->time_next_packet = now;
        f->credit -= qdisc_pkt_len(skb);
 
-       if (f->credit <= 0 &&
-           q->rate_enable &&
-           skb->sk && skb->sk->sk_state != TCP_TIME_WAIT) {
-               u32 rate = skb->sk->sk_pacing_rate ?: q->flow_default_rate;
+       if (f->credit > 0 || !q->rate_enable)
+               goto out;
 
-               rate = min(rate, q->flow_max_rate);
-               if (rate) {
-                       u64 len = (u64)qdisc_pkt_len(skb) * NSEC_PER_SEC;
-
-                       do_div(len, rate);
-                       /* Since socket rate can change later,
-                        * clamp the delay to 125 ms.
-                        * TODO: maybe segment the too big skb, as in commit
-                        * e43ac79a4bc ("sch_tbf: segment too big GSO packets")
-                        */
-                       if (unlikely(len > 125 * NSEC_PER_MSEC)) {
-                               len = 125 * NSEC_PER_MSEC;
-                               q->stat_pkts_too_long++;
-                       }
+       if (skb->sk && skb->sk->sk_state != TCP_TIME_WAIT) {
+               rate = skb->sk->sk_pacing_rate ?: q->flow_default_rate;
 
-                       f->time_next_packet = now + len;
+               rate = min(rate, q->flow_max_rate);
+       } else {
+               rate = q->flow_max_rate;
+               if (rate == ~0U)
+                       goto out;
+       }
+       if (rate) {
+               u32 plen = max(qdisc_pkt_len(skb), q->quantum);
+               u64 len = (u64)plen * NSEC_PER_SEC;
+
+               do_div(len, rate);
+               /* Since socket rate can change later,
+                * clamp the delay to 125 ms.
+                * TODO: maybe segment the too big skb, as in commit
+                * e43ac79a4bc ("sch_tbf: segment too big GSO packets")
+                */
+               if (unlikely(len > 125 * NSEC_PER_MSEC)) {
+                       len = 125 * NSEC_PER_MSEC;
+                       q->stat_pkts_too_long++;
                }
+
+               f->time_next_packet = now + len;
        }
 out:
-       sch->qstats.backlog -= qdisc_pkt_len(skb);
        qdisc_bstats_update(sch, skb);
-       sch->q.qlen--;
        qdisc_unthrottled(sch);
        return skb;
 }
 
 static void fq_reset(struct Qdisc *sch)
 {
+       struct fq_sched_data *q = qdisc_priv(sch);
+       struct rb_root *root;
        struct sk_buff *skb;
+       struct rb_node *p;
+       struct fq_flow *f;
+       unsigned int idx;
 
-       while ((skb = fq_dequeue(sch)) != NULL)
+       while ((skb = fq_dequeue_head(sch, &q->internal)) != NULL)
                kfree_skb(skb);
+
+       if (!q->fq_root)
+               return;
+
+       for (idx = 0; idx < (1U << q->fq_trees_log); idx++) {
+               root = &q->fq_root[idx];
+               while ((p = rb_first(root)) != NULL) {
+                       f = container_of(p, struct fq_flow, fq_node);
+                       rb_erase(p, root);
+
+                       while ((skb = fq_dequeue_head(sch, f)) != NULL)
+                               kfree_skb(skb);
+
+                       kmem_cache_free(fq_flow_cachep, f);
+               }
+       }
+       q->new_flows.first      = NULL;
+       q->old_flows.first      = NULL;
+       q->delayed              = RB_ROOT;
+       q->flows                = 0;
+       q->inactive_flows       = 0;
+       q->throttled_flows      = 0;
 }
 
 static void fq_rehash(struct fq_sched_data *q,
@@ -645,6 +679,8 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt)
        while (sch->q.qlen > sch->limit) {
                struct sk_buff *skb = fq_dequeue(sch);
 
+               if (!skb)
+                       break;
                kfree_skb(skb);
                drop_count++;
        }
@@ -657,21 +693,9 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt)
 static void fq_destroy(struct Qdisc *sch)
 {
        struct fq_sched_data *q = qdisc_priv(sch);
-       struct rb_root *root;
-       struct rb_node *p;
-       unsigned int idx;
 
-       if (q->fq_root) {
-               for (idx = 0; idx < (1U << q->fq_trees_log); idx++) {
-                       root = &q->fq_root[idx];
-                       while ((p = rb_first(root)) != NULL) {
-                               rb_erase(p, root);
-                               kmem_cache_free(fq_flow_cachep,
-                                               container_of(p, struct fq_flow, fq_node));
-                       }
-               }
-               kfree(q->fq_root);
-       }
+       fq_reset(sch);
+       kfree(q->fq_root);
        qdisc_watchdog_cancel(&q->watchdog);
 }
 
index 5f2068679f8339b8a85b85cf2dc7b185a663dd9c..98b69bbecdd96eadcbaeb3bdecc210dcca2ab11d 100644 (file)
@@ -634,8 +634,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
                break;
        case ICMP_REDIRECT:
                sctp_icmp_redirect(sk, transport, skb);
-               err = 0;
-               break;
+               /* Fall through to out_unlock. */
        default:
                goto out_unlock;
        }
index da613ceae28cc95b38dc1a3d7366c2f38b348d9b..e7b2d4fe2b6a120c66b3e869d796eb6dba69c2d2 100644 (file)
@@ -183,7 +183,7 @@ static void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                break;
        case NDISC_REDIRECT:
                sctp_icmp_redirect(sk, transport, skb);
-               break;
+               goto out_unlock;
        default:
                break;
        }
@@ -204,44 +204,23 @@ out:
                in6_dev_put(idev);
 }
 
-/* Based on tcp_v6_xmit() in tcp_ipv6.c. */
 static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)
 {
        struct sock *sk = skb->sk;
        struct ipv6_pinfo *np = inet6_sk(sk);
-       struct flowi6 fl6;
-
-       memset(&fl6, 0, sizeof(fl6));
-
-       fl6.flowi6_proto = sk->sk_protocol;
-
-       /* Fill in the dest address from the route entry passed with the skb
-        * and the source address from the transport.
-        */
-       fl6.daddr = transport->ipaddr.v6.sin6_addr;
-       fl6.saddr = transport->saddr.v6.sin6_addr;
-
-       fl6.flowlabel = np->flow_label;
-       IP6_ECN_flow_xmit(sk, fl6.flowlabel);
-       if (ipv6_addr_type(&fl6.saddr) & IPV6_ADDR_LINKLOCAL)
-               fl6.flowi6_oif = transport->saddr.v6.sin6_scope_id;
-       else
-               fl6.flowi6_oif = sk->sk_bound_dev_if;
-
-       if (np->opt && np->opt->srcrt) {
-               struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
-               fl6.daddr = *rt0->addr;
-       }
+       struct flowi6 *fl6 = &transport->fl.u.ip6;
 
        pr_debug("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", __func__, skb,
-                skb->len, &fl6.saddr, &fl6.daddr);
+                skb->len, &fl6->saddr, &fl6->daddr);
 
-       SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS);
+       IP6_ECN_flow_xmit(sk, fl6->flowlabel);
 
        if (!(transport->param_flags & SPP_PMTUD_ENABLE))
                skb->local_df = 1;
 
-       return ip6_xmit(sk, skb, &fl6, np->opt, np->tclass);
+       SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS);
+
+       return ip6_xmit(sk, skb, fl6, np->opt, np->tclass);
 }
 
 /* Returns the dst cache entry for the given source and destination ip
@@ -254,10 +233,12 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
        struct dst_entry *dst = NULL;
        struct flowi6 *fl6 = &fl->u.ip6;
        struct sctp_bind_addr *bp;
+       struct ipv6_pinfo *np = inet6_sk(sk);
        struct sctp_sockaddr_entry *laddr;
        union sctp_addr *baddr = NULL;
        union sctp_addr *daddr = &t->ipaddr;
        union sctp_addr dst_saddr;
+       struct in6_addr *final_p, final;
        __u8 matchlen = 0;
        __u8 bmatchlen;
        sctp_scope_t scope;
@@ -281,7 +262,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
                pr_debug("src=%pI6 - ", &fl6->saddr);
        }
 
-       dst = ip6_dst_lookup_flow(sk, fl6, NULL, false);
+       final_p = fl6_update_dst(fl6, np->opt, &final);
+       dst = ip6_dst_lookup_flow(sk, fl6, final_p, false);
        if (!asoc || saddr)
                goto out;
 
@@ -333,10 +315,12 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
                }
        }
        rcu_read_unlock();
+
        if (baddr) {
                fl6->saddr = baddr->v6.sin6_addr;
                fl6->fl6_sport = baddr->v6.sin6_port;
-               dst = ip6_dst_lookup_flow(sk, fl6, NULL, false);
+               final_p = fl6_update_dst(fl6, np->opt, &final);
+               dst = ip6_dst_lookup_flow(sk, fl6, final_p, false);
        }
 
 out:
index fcac5d14171779a32599e6b4111b75a8e94a15aa..084656671d6ee4cebc6220ad0d92bae654497882 100644 (file)
@@ -1075,6 +1075,15 @@ gss_destroy(struct rpc_auth *auth)
        kref_put(&gss_auth->kref, gss_free_callback);
 }
 
+/*
+ * Auths may be shared between rpc clients that were cloned from a
+ * common client with the same xprt, if they also share the flavor and
+ * target_name.
+ *
+ * The auth is looked up from the oldest parent sharing the same
+ * cl_xprt, and the auth itself references only that common parent
+ * (which is guaranteed to last as long as any of its descendants).
+ */
 static struct gss_auth *
 gss_auth_find_or_add_hashed(struct rpc_auth_create_args *args,
                struct rpc_clnt *clnt,
@@ -1088,6 +1097,8 @@ gss_auth_find_or_add_hashed(struct rpc_auth_create_args *args,
                        gss_auth,
                        hash,
                        hashval) {
+               if (gss_auth->client != clnt)
+                       continue;
                if (gss_auth->rpc_auth.au_flavor != args->pseudoflavor)
                        continue;
                if (gss_auth->target_name != args->target_name) {
index 9bc6db04be3ea7cd998f41187ff40b19baa9c920..e7000be321b0148469264524ed6fce75c3952955 100644 (file)
@@ -47,12 +47,12 @@ static int net_ctl_permissions(struct ctl_table_header *head,
 
        /* Allow network administrator to have same access as root. */
        if (ns_capable(net->user_ns, CAP_NET_ADMIN) ||
-           uid_eq(root_uid, current_uid())) {
+           uid_eq(root_uid, current_euid())) {
                int mode = (table->mode >> 6) & 7;
                return (mode << 6) | (mode << 3) | mode;
        }
        /* Allow netns root group to have the same access as the root group */
-       if (gid_eq(root_gid, current_gid())) {
+       if (in_egroup_p(root_gid)) {
                int mode = (table->mode >> 3) & 7;
                return (mode << 3) | mode;
        }
index 47016c304c847efffb96da5358224a9b5a93cc5e..66cad506b8a2a944f2873856ef0078445f673b8b 100755 (executable)
@@ -3975,8 +3975,8 @@ sub string_find_replace {
 # check for new externs in .h files.
                if ($realfile =~ /\.h$/ &&
                    $line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) {
-                       if (WARN("AVOID_EXTERNS",
-                                "extern prototypes should be avoided in .h files\n" . $herecurr) &&
+                       if (CHK("AVOID_EXTERNS",
+                               "extern prototypes should be avoided in .h files\n" . $herecurr) &&
                            $fix) {
                                $fixed[$linenr - 1] =~ s/(.*)\bextern\b\s*(.*)/$1$2/;
                        }
index d6222ba4e9190207f3ddabbb58161e25f397169b..532471d0b3a0facd6c7cb70a930e4028ca6d0761 100644 (file)
  * it should be.
  */
 
-#include <linux/crypto.h>
+#include <crypto/hash.h>
 
 #include "include/apparmor.h"
 #include "include/crypto.h"
 
 static unsigned int apparmor_hash_size;
 
-static struct crypto_hash *apparmor_tfm;
+static struct crypto_shash *apparmor_tfm;
 
 unsigned int aa_hash_size(void)
 {
@@ -32,35 +32,33 @@ unsigned int aa_hash_size(void)
 int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start,
                         size_t len)
 {
-       struct scatterlist sg[2];
-       struct hash_desc desc = {
-               .tfm = apparmor_tfm,
-               .flags = 0
-       };
+       struct {
+               struct shash_desc shash;
+               char ctx[crypto_shash_descsize(apparmor_tfm)];
+       } desc;
        int error = -ENOMEM;
        u32 le32_version = cpu_to_le32(version);
 
        if (!apparmor_tfm)
                return 0;
 
-       sg_init_table(sg, 2);
-       sg_set_buf(&sg[0], &le32_version, 4);
-       sg_set_buf(&sg[1], (u8 *) start, len);
-
        profile->hash = kzalloc(apparmor_hash_size, GFP_KERNEL);
        if (!profile->hash)
                goto fail;
 
-       error = crypto_hash_init(&desc);
+       desc.shash.tfm = apparmor_tfm;
+       desc.shash.flags = 0;
+
+       error = crypto_shash_init(&desc.shash);
        if (error)
                goto fail;
-       error = crypto_hash_update(&desc, &sg[0], 4);
+       error = crypto_shash_update(&desc.shash, (u8 *) &le32_version, 4);
        if (error)
                goto fail;
-       error = crypto_hash_update(&desc, &sg[1], len);
+       error = crypto_shash_update(&desc.shash, (u8 *) start, len);
        if (error)
                goto fail;
-       error = crypto_hash_final(&desc, profile->hash);
+       error = crypto_shash_final(&desc.shash, profile->hash);
        if (error)
                goto fail;
 
@@ -75,19 +73,19 @@ fail:
 
 static int __init init_profile_hash(void)
 {
-       struct crypto_hash *tfm;
+       struct crypto_shash *tfm;
 
        if (!apparmor_initialized)
                return 0;
 
-       tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC);
+       tfm = crypto_alloc_shash("sha1", 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(tfm)) {
                int error = PTR_ERR(tfm);
                AA_ERROR("failed to setup profile sha1 hashing: %d\n", error);
                return error;
        }
        apparmor_tfm = tfm;
-       apparmor_hash_size = crypto_hash_digestsize(apparmor_tfm);
+       apparmor_hash_size = crypto_shash_digestsize(apparmor_tfm);
 
        aa_info_message("AppArmor sha1 policy hashing enabled");
 
index f2d4b6348cbc0a5f1ec0abdc0d2d975ad34ce493..c28b0f20ab53ed69da7c1e6b8c60a8099370a4f8 100644 (file)
@@ -360,7 +360,9 @@ static inline void aa_put_replacedby(struct aa_replacedby *p)
 static inline void __aa_update_replacedby(struct aa_profile *orig,
                                          struct aa_profile *new)
 {
-       struct aa_profile *tmp = rcu_dereference(orig->replacedby->profile);
+       struct aa_profile *tmp;
+       tmp = rcu_dereference_protected(orig->replacedby->profile,
+                                       mutex_is_locked(&orig->ns->lock));
        rcu_assign_pointer(orig->replacedby->profile, aa_get_profile(new));
        orig->flags |= PFLAG_INVALID;
        aa_put_profile(tmp);
index 6172509fa2b7441fbda60d1cd6e5b35fce432dc8..345bec07a27d9292dbfc1306d1f5e12563eaa891 100644 (file)
@@ -563,7 +563,8 @@ void __init aa_free_root_ns(void)
 static void free_replacedby(struct aa_replacedby *r)
 {
        if (r) {
-               aa_put_profile(rcu_dereference(r->profile));
+               /* r->profile will not be updated any more as r is dead */
+               aa_put_profile(rcu_dereference_protected(r->profile, true));
                kzfree(r);
        }
 }
index dad36a6ab45f628860ef4c5c097d2a5abce15b4a..fc3e6628a8642e027c992cf500fd4c0a921c85fc 100644 (file)
@@ -746,7 +746,6 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid,
  * @tclass: target security class
  * @requested: requested permissions, interpreted based on @tclass
  * @auditdata: auxiliary audit data
- * @flags: VFS walk flags
  *
  * Check the AVC to determine whether the @requested permissions are granted
  * for the SID pair (@ssid, @tsid), interpreting the permissions
@@ -756,17 +755,15 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid,
  * permissions are granted, -%EACCES if any permissions are denied, or
  * another -errno upon other errors.
  */
-int avc_has_perm_flags(u32 ssid, u32 tsid, u16 tclass,
-                      u32 requested, struct common_audit_data *auditdata,
-                      unsigned flags)
+int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
+                u32 requested, struct common_audit_data *auditdata)
 {
        struct av_decision avd;
        int rc, rc2;
 
        rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd);
 
-       rc2 = avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata,
-                       flags);
+       rc2 = avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
        if (rc2)
                return rc2;
        return rc;
index a5091ec06aa62816798510e40a1bcf005d2abd3d..5b5231068516e46bb529efb3df38051124d2ef85 100644 (file)
@@ -1502,7 +1502,7 @@ static int cred_has_capability(const struct cred *cred,
 
        rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
        if (audit == SECURITY_CAP_AUDIT) {
-               int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
+               int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad);
                if (rc2)
                        return rc2;
        }
@@ -1525,8 +1525,7 @@ static int task_has_system(struct task_struct *tsk,
 static int inode_has_perm(const struct cred *cred,
                          struct inode *inode,
                          u32 perms,
-                         struct common_audit_data *adp,
-                         unsigned flags)
+                         struct common_audit_data *adp)
 {
        struct inode_security_struct *isec;
        u32 sid;
@@ -1539,7 +1538,7 @@ static int inode_has_perm(const struct cred *cred,
        sid = cred_sid(cred);
        isec = inode->i_security;
 
-       return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
+       return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
 }
 
 /* Same as inode_has_perm, but pass explicit audit data containing
@@ -1554,7 +1553,7 @@ static inline int dentry_has_perm(const struct cred *cred,
 
        ad.type = LSM_AUDIT_DATA_DENTRY;
        ad.u.dentry = dentry;
-       return inode_has_perm(cred, inode, av, &ad, 0);
+       return inode_has_perm(cred, inode, av, &ad);
 }
 
 /* Same as inode_has_perm, but pass explicit audit data containing
@@ -1569,7 +1568,7 @@ static inline int path_has_perm(const struct cred *cred,
 
        ad.type = LSM_AUDIT_DATA_PATH;
        ad.u.path = *path;
-       return inode_has_perm(cred, inode, av, &ad, 0);
+       return inode_has_perm(cred, inode, av, &ad);
 }
 
 /* Same as path_has_perm, but uses the inode from the file struct. */
@@ -1581,7 +1580,7 @@ static inline int file_path_has_perm(const struct cred *cred,
 
        ad.type = LSM_AUDIT_DATA_PATH;
        ad.u.path = file->f_path;
-       return inode_has_perm(cred, file_inode(file), av, &ad, 0);
+       return inode_has_perm(cred, file_inode(file), av, &ad);
 }
 
 /* Check whether a task can use an open file descriptor to
@@ -1617,7 +1616,7 @@ static int file_has_perm(const struct cred *cred,
        /* av is zero if only checking access to the descriptor. */
        rc = 0;
        if (av)
-               rc = inode_has_perm(cred, inode, av, &ad, 0);
+               rc = inode_has_perm(cred, inode, av, &ad);
 
 out:
        return rc;
index 92d0ab561db80cb4aa253815149a35e02d6175d1..f53ee3c58d0ffd5099879f2bcdc160c88c209c86 100644 (file)
@@ -130,7 +130,7 @@ static inline int avc_audit(u32 ssid, u32 tsid,
                            u16 tclass, u32 requested,
                            struct av_decision *avd,
                            int result,
-                           struct common_audit_data *a, unsigned flags)
+                           struct common_audit_data *a)
 {
        u32 audited, denied;
        audited = avc_audit_required(requested, avd, result, 0, &denied);
@@ -138,7 +138,7 @@ static inline int avc_audit(u32 ssid, u32 tsid,
                return 0;
        return slow_avc_audit(ssid, tsid, tclass,
                              requested, audited, denied,
-                             a, flags);
+                             a, 0);
 }
 
 #define AVC_STRICT 1 /* Ignore permissive mode. */
@@ -147,17 +147,9 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
                         unsigned flags,
                         struct av_decision *avd);
 
-int avc_has_perm_flags(u32 ssid, u32 tsid,
-                      u16 tclass, u32 requested,
-                      struct common_audit_data *auditdata,
-                      unsigned);
-
-static inline int avc_has_perm(u32 ssid, u32 tsid,
-                              u16 tclass, u32 requested,
-                              struct common_audit_data *auditdata)
-{
-       return avc_has_perm_flags(ssid, tsid, tclass, requested, auditdata, 0);
-}
+int avc_has_perm(u32 ssid, u32 tsid,
+                u16 tclass, u32 requested,
+                struct common_audit_data *auditdata);
 
 u32 avc_policy_seqno(void);
 
index 69a2455b447210d42c2bf2c37b23fbe9035eada9..e6c727b317fbd8fa5a1d33fef7133aa601eeddd7 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
 
 #include <sound/core.h>
@@ -83,8 +84,6 @@ static struct snd_pcm_ops pxa2xx_pcm_ops = {
        .mmap           = pxa2xx_pcm_mmap,
 };
 
-static u64 pxa2xx_pcm_dmamask = 0xffffffff;
-
 int pxa2xx_pcm_new(struct snd_card *card, struct pxa2xx_pcm_client *client,
                   struct snd_pcm **rpcm)
 {
@@ -100,10 +99,9 @@ int pxa2xx_pcm_new(struct snd_card *card, struct pxa2xx_pcm_client *client,
        pcm->private_data = client;
        pcm->private_free = pxa2xx_pcm_free_dma_buffers;
 
-       if (!card->dev->dma_mask)
-               card->dev->dma_mask = &pxa2xx_pcm_dmamask;
-       if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = 0xffffffff;
+       ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+       if (ret)
+               goto out;
 
        if (play) {
                int stream = SNDRV_PCM_STREAM_PLAYBACK;
index 98969541cbcc9c62ff81afb9818d2399dd6e7eb0..bea523a5d852e11f9d06e1d682e065b699f347c8 100644 (file)
@@ -139,6 +139,18 @@ static int snd_compr_open(struct inode *inode, struct file *f)
 static int snd_compr_free(struct inode *inode, struct file *f)
 {
        struct snd_compr_file *data = f->private_data;
+       struct snd_compr_runtime *runtime = data->stream.runtime;
+
+       switch (runtime->state) {
+       case SNDRV_PCM_STATE_RUNNING:
+       case SNDRV_PCM_STATE_DRAINING:
+       case SNDRV_PCM_STATE_PAUSED:
+               data->stream.ops->trigger(&data->stream, SNDRV_PCM_TRIGGER_STOP);
+               break;
+       default:
+               break;
+       }
+
        data->stream.ops->free(&data->stream);
        kfree(data->stream.runtime->buffer);
        kfree(data->stream.runtime);
@@ -837,7 +849,8 @@ static int snd_compress_dev_disconnect(struct snd_device *device)
        struct snd_compr *compr;
 
        compr = device->device_data;
-       snd_unregister_device(compr->direction, compr->card, compr->device);
+       snd_unregister_device(SNDRV_DEVICE_TYPE_COMPRESS, compr->card,
+               compr->device);
        return 0;
 }
 
index 445ca481d8d30116bc075e3ac2cee881f1149863..bf578ba2677e72566187619e1e0515afe93fdfd6 100644 (file)
@@ -175,6 +175,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = {
 { 0x54524106, 0xffffffff, "TR28026",           NULL,           NULL },
 { 0x54524108, 0xffffffff, "TR28028",           patch_tritech_tr28028,  NULL }, // added by xin jin [07/09/99]
 { 0x54524123, 0xffffffff, "TR28602",           NULL,           NULL }, // only guess --jk [TR28023 = eMicro EM28023 (new CT1297)]
+{ 0x54584e03, 0xffffffff, "TLV320AIC27",       NULL,           NULL },
 { 0x54584e20, 0xffffffff, "TLC320AD9xC",       NULL,           NULL },
 { 0x56494161, 0xffffffff, "VIA1612A",          NULL,           NULL }, // modified ICE1232 with S/PDIF
 { 0x56494170, 0xffffffff, "VIA1617A",          patch_vt1617a,  NULL }, // modified VT1616 with S/PDIF
index b524f89a1f13a7d74c51c8231684f971662ccc15..18d9725015855c0ce3f33d174a3dfcd55836efeb 100644 (file)
@@ -111,6 +111,9 @@ enum {
 /* 0x0009 - 0x0014 -> 12 test regs */
 /* 0x0015 - visibility reg */
 
+/* Cirrus Logic CS4208 */
+#define CS4208_VENDOR_NID      0x24
+
 /*
  * Cirrus Logic CS4210
  *
@@ -223,6 +226,16 @@ static const struct hda_verb cs_coef_init_verbs[] = {
        {} /* terminator */
 };
 
+static const struct hda_verb cs4208_coef_init_verbs[] = {
+       {0x01, AC_VERB_SET_POWER_STATE, 0x00}, /* AFG: D0 */
+       {0x24, AC_VERB_SET_PROC_STATE, 0x01},  /* VPW: processing on */
+       {0x24, AC_VERB_SET_COEF_INDEX, 0x0033},
+       {0x24, AC_VERB_SET_PROC_COEF, 0x0001}, /* A1 ICS */
+       {0x24, AC_VERB_SET_COEF_INDEX, 0x0034},
+       {0x24, AC_VERB_SET_PROC_COEF, 0x1C01}, /* A1 Enable, A Thresh = 300mV */
+       {} /* terminator */
+};
+
 /* Errata: CS4207 rev C0/C1/C2 Silicon
  *
  * http://www.cirrus.com/en/pubs/errata/ER880C3.pdf
@@ -295,6 +308,8 @@ static int cs_init(struct hda_codec *codec)
                /* init_verb sequence for C0/C1/C2 errata*/
                snd_hda_sequence_write(codec, cs_errata_init_verbs);
                snd_hda_sequence_write(codec, cs_coef_init_verbs);
+       } else if (spec->vendor_nid == CS4208_VENDOR_NID) {
+               snd_hda_sequence_write(codec, cs4208_coef_init_verbs);
        }
 
        snd_hda_gen_init(codec);
@@ -434,6 +449,29 @@ static const struct hda_pintbl mba42_pincfgs[] = {
        {} /* terminator */
 };
 
+static const struct hda_pintbl mba6_pincfgs[] = {
+       { 0x10, 0x032120f0 }, /* HP */
+       { 0x11, 0x500000f0 },
+       { 0x12, 0x90100010 }, /* Speaker */
+       { 0x13, 0x500000f0 },
+       { 0x14, 0x500000f0 },
+       { 0x15, 0x770000f0 },
+       { 0x16, 0x770000f0 },
+       { 0x17, 0x430000f0 },
+       { 0x18, 0x43ab9030 }, /* Mic */
+       { 0x19, 0x770000f0 },
+       { 0x1a, 0x770000f0 },
+       { 0x1b, 0x770000f0 },
+       { 0x1c, 0x90a00090 },
+       { 0x1d, 0x500000f0 },
+       { 0x1e, 0x500000f0 },
+       { 0x1f, 0x500000f0 },
+       { 0x20, 0x500000f0 },
+       { 0x21, 0x430000f0 },
+       { 0x22, 0x430000f0 },
+       {} /* terminator */
+};
+
 static void cs420x_fixup_gpio_13(struct hda_codec *codec,
                                 const struct hda_fixup *fix, int action)
 {
@@ -556,22 +594,23 @@ static int patch_cs420x(struct hda_codec *codec)
 
 /*
  * CS4208 support:
- * Its layout is no longer compatible with CS4206/CS4207, and the generic
- * parser seems working fairly well, except for trivial fixups.
+ * Its layout is no longer compatible with CS4206/CS4207
  */
 enum {
+       CS4208_MBA6,
        CS4208_GPIO0,
 };
 
 static const struct hda_model_fixup cs4208_models[] = {
        { .id = CS4208_GPIO0, .name = "gpio0" },
+       { .id = CS4208_MBA6, .name = "mba6" },
        {}
 };
 
 static const struct snd_pci_quirk cs4208_fixup_tbl[] = {
        /* codec SSID */
-       SND_PCI_QUIRK(0x106b, 0x7100, "MacBookPro 6,1", CS4208_GPIO0),
-       SND_PCI_QUIRK(0x106b, 0x7200, "MacBookPro 6,2", CS4208_GPIO0),
+       SND_PCI_QUIRK(0x106b, 0x7100, "MacBookAir 6,1", CS4208_MBA6),
+       SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6),
        {} /* terminator */
 };
 
@@ -588,18 +627,35 @@ static void cs4208_fixup_gpio0(struct hda_codec *codec,
 }
 
 static const struct hda_fixup cs4208_fixups[] = {
+       [CS4208_MBA6] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = mba6_pincfgs,
+               .chained = true,
+               .chain_id = CS4208_GPIO0,
+       },
        [CS4208_GPIO0] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = cs4208_fixup_gpio0,
        },
 };
 
+/* correct the 0dB offset of input pins */
+static void cs4208_fix_amp_caps(struct hda_codec *codec, hda_nid_t adc)
+{
+       unsigned int caps;
+
+       caps = query_amp_caps(codec, adc, HDA_INPUT);
+       caps &= ~(AC_AMPCAP_OFFSET);
+       caps |= 0x02;
+       snd_hda_override_amp_caps(codec, adc, HDA_INPUT, caps);
+}
+
 static int patch_cs4208(struct hda_codec *codec)
 {
        struct cs_spec *spec;
        int err;
 
-       spec = cs_alloc_spec(codec, 0); /* no specific w/a */
+       spec = cs_alloc_spec(codec, CS4208_VENDOR_NID);
        if (!spec)
                return -ENOMEM;
 
@@ -609,6 +665,12 @@ static int patch_cs4208(struct hda_codec *codec)
                           cs4208_fixups);
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 
+       snd_hda_override_wcaps(codec, 0x18,
+                              get_wcaps(codec, 0x18) | AC_WCAP_STEREO);
+       cs4208_fix_amp_caps(codec, 0x18);
+       cs4208_fix_amp_caps(codec, 0x1b);
+       cs4208_fix_amp_caps(codec, 0x1c);
+
        err = cs_parse_auto_config(codec);
        if (err < 0)
                goto error;
index 4edd2d0f9a3ce66e625f7576b3b7053548397a51..ec68eaea0336a008c78fb05c03a4d6c0e3f99c2a 100644 (file)
@@ -3231,6 +3231,7 @@ enum {
        CXT_FIXUP_INC_MIC_BOOST,
        CXT_FIXUP_HEADPHONE_MIC_PIN,
        CXT_FIXUP_HEADPHONE_MIC,
+       CXT_FIXUP_GPIO1,
 };
 
 static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
@@ -3375,6 +3376,15 @@ static const struct hda_fixup cxt_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = cxt_fixup_headphone_mic,
        },
+       [CXT_FIXUP_GPIO1] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       { 0x01, AC_VERB_SET_GPIO_MASK, 0x01 },
+                       { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01 },
+                       { 0x01, AC_VERB_SET_GPIO_DATA, 0x01 },
+                       { }
+               },
+       },
 };
 
 static const struct snd_pci_quirk cxt5051_fixups[] = {
@@ -3384,6 +3394,7 @@ static const struct snd_pci_quirk cxt5051_fixups[] = {
 
 static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC),
+       SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_GPIO1),
        SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
        SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410),
index 3d8cd04455a623b888a9efccb7bdd31f92df8188..7ea0245fc6bd5fe5579d81682a2d39ce6cd06af7 100644 (file)
@@ -1149,32 +1149,43 @@ static int hdmi_choose_cvt(struct hda_codec *codec,
 }
 
 static void haswell_config_cvts(struct hda_codec *codec,
-                       int pin_id, int mux_id)
+                       hda_nid_t pin_nid, int mux_idx)
 {
        struct hdmi_spec *spec = codec->spec;
-       struct hdmi_spec_per_pin *per_pin;
-       int pin_idx, mux_idx;
-       int curr;
-       int err;
+       hda_nid_t nid, end_nid;
+       int cvt_idx, curr;
+       struct hdmi_spec_per_cvt *per_cvt;
 
-       for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
-               per_pin = get_pin(spec, pin_idx);
+       /* configure all pins, including "no physical connection" ones */
+       end_nid = codec->start_nid + codec->num_nodes;
+       for (nid = codec->start_nid; nid < end_nid; nid++) {
+               unsigned int wid_caps = get_wcaps(codec, nid);
+               unsigned int wid_type = get_wcaps_type(wid_caps);
 
-               if (pin_idx == pin_id)
+               if (wid_type != AC_WID_PIN)
                        continue;
 
-               curr = snd_hda_codec_read(codec, per_pin->pin_nid, 0,
+               if (nid == pin_nid)
+                       continue;
+
+               curr = snd_hda_codec_read(codec, nid, 0,
                                          AC_VERB_GET_CONNECT_SEL, 0);
+               if (curr != mux_idx)
+                       continue;
 
-               /* Choose another unused converter */
-               if (curr == mux_id) {
-                       err = hdmi_choose_cvt(codec, pin_idx, NULL, &mux_idx);
-                       if (err < 0)
-                               return;
-                       snd_printdd("HDMI: choose converter %d for pin %d\n", mux_idx, pin_idx);
-                       snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
+               /* choose an unassigned converter. The conveters in the
+                * connection list are in the same order as in the codec.
+                */
+               for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) {
+                       per_cvt = get_cvt(spec, cvt_idx);
+                       if (!per_cvt->assigned) {
+                               snd_printdd("choose cvt %d for pin nid %d\n",
+                                       cvt_idx, nid);
+                               snd_hda_codec_write_cache(codec, nid, 0,
                                            AC_VERB_SET_CONNECT_SEL,
-                                           mux_idx);
+                                           cvt_idx);
+                               break;
+                       }
                }
        }
 }
@@ -1216,7 +1227,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
 
        /* configure unused pins to choose other converters */
        if (is_haswell(codec))
-               haswell_config_cvts(codec, pin_idx, mux_idx);
+               haswell_config_cvts(codec, per_pin->pin_nid, mux_idx);
 
        snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid);
 
index bc07d369fac43a548db7f1e45273627cc4e7246c..0e303b99a47ceef3037e7b245ed5d93caf1f7779 100644 (file)
@@ -3439,6 +3439,9 @@ static void alc283_fixup_chromebook(struct hda_codec *codec,
                /* Set to manual mode */
                val = alc_read_coef_idx(codec, 0x06);
                alc_write_coef_idx(codec, 0x06, val & ~0x000c);
+               /* Enable Line1 input control by verb */
+               val = alc_read_coef_idx(codec, 0x1a);
+               alc_write_coef_idx(codec, 0x1a, val | (1 << 4));
                break;
        }
 }
@@ -3531,6 +3534,7 @@ enum {
        ALC269VB_FIXUP_ORDISSIMO_EVE2,
        ALC283_FIXUP_CHROME_BOOK,
        ALC282_FIXUP_ASUS_TX300,
+       ALC283_FIXUP_INT_MIC,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -3790,6 +3794,16 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc282_fixup_asus_tx300,
        },
+       [ALC283_FIXUP_INT_MIC] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       {0x20, AC_VERB_SET_COEF_INDEX, 0x1a},
+                       {0x20, AC_VERB_SET_PROC_COEF, 0x0011},
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -3874,7 +3888,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
-       SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
+       SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC),
        SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
index 3109db7b9017cc08dd23ef6f9c70f9c605bcdf3e..fbb87e3f10193c1077596e90b6bb7f73d8fb215c 100644 (file)
@@ -68,18 +68,15 @@ int atmel_pcm_mmap(struct snd_pcm_substream *substream,
 }
 EXPORT_SYMBOL_GPL(atmel_pcm_mmap);
 
-static u64 atmel_pcm_dmamask = DMA_BIT_MASK(32);
-
 int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_pcm *pcm = rtd->pcm;
-       int ret = 0;
+       int ret;
 
-       if (!card->dev->dma_mask)
-               card->dev->dma_mask = &atmel_pcm_dmamask;
-       if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                pr_debug("atmel-pcm: allocating PCM playback DMA buffer\n");
index 53f84085bf1fbd7c1daadc093ebd60d7f5dc7251..1d4c676eb6cc696e78f6722525923c91e3afe936 100644 (file)
@@ -415,19 +415,16 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
        }
 }
 
-static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
-
 static int bf5xx_pcm_ac97_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_pcm *pcm = rtd->pcm;
-       int ret = 0;
+       int ret;
 
        pr_debug("%s enter\n", __func__);
-       if (!card->dev->dma_mask)
-               card->dev->dma_mask = &bf5xx_pcm_dmamask;
-       if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
index 9cb4a80df98eee2efa78b9b3a05a99baf64cc8b1..2a5b43417fd5a5810ac36d1cc258f97987e9066a 100644 (file)
@@ -323,18 +323,16 @@ static struct snd_pcm_ops bf5xx_pcm_i2s_ops = {
        .silence        = bf5xx_pcm_silence,
 };
 
-static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
-
 static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        size_t size = bf5xx_pcm_hardware.buffer_bytes_max;
+       int ret;
 
        pr_debug("%s enter\n", __func__);
-       if (!card->dev->dma_mask)
-               card->dev->dma_mask = &bf5xx_pcm_dmamask;
-       if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
                                SNDRV_DMA_TYPE_DEV, card->dev, size, size);
index c02405cc007db2c88c14b25d17eff81b270f550b..5810a0603f2f1eb17ef5eece60d97ba7f6687e04 100644 (file)
@@ -88,6 +88,7 @@ static int bfin_i2s_hw_params(struct snd_pcm_substream *substream,
        case SNDRV_PCM_FORMAT_S8:
                param.spctl |= 0x70;
                sport->wdsize = 1;
+               break;
        case SNDRV_PCM_FORMAT_S16_LE:
                param.spctl |= 0xf0;
                sport->wdsize = 2;
index 8af04343cc1ac9eab35fe951fd079fd1954da462..259d1ac4492fc610a1454567bdabd52f56dbae5a 100644 (file)
@@ -349,6 +349,9 @@ static int snd_soc_put_volsw_2r_st(struct snd_kcontrol *kcontrol,
        val = ucontrol->value.integer.value[0];
        val2 = ucontrol->value.integer.value[1];
 
+       if (val >= ARRAY_SIZE(st_table) || val2 >= ARRAY_SIZE(st_table))
+               return -EINVAL;
+
        err = snd_soc_update_bits(codec, reg, 0x3f, st_table[val].m);
        if (err < 0)
                return err;
index b8ba0adacfce1229989f0114ce25eb9711f61d16..80555d7551e68018d5e66485eea1507b10c35b92 100644 (file)
@@ -1225,13 +1225,18 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol,
        struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
        struct device *dev = codec->dev;
        bool apply_fir, apply_iir;
-       int req, status;
+       unsigned int req;
+       int status;
 
        dev_dbg(dev, "%s: Enter.\n", __func__);
 
        mutex_lock(&drvdata->anc_lock);
 
        req = ucontrol->value.integer.value[0];
+       if (req >= ARRAY_SIZE(enum_anc_state)) {
+               status = -EINVAL;
+               goto cleanup;
+       }
        if (req != ANC_APPLY_FIR_IIR && req != ANC_APPLY_FIR &&
                req != ANC_APPLY_IIR) {
                dev_err(dev, "%s: ERROR: Unsupported status to set '%s'!\n",
index 41cdd164297046c3045c9463ab6183810e02a126..8dbcacd44e6aa5cbf5de1fba91ebdf16c1592ff8 100644 (file)
@@ -1863,7 +1863,7 @@ static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol,
        struct max98095_pdata *pdata = max98095->pdata;
        int channel = max98095_get_eq_channel(kcontrol->id.name);
        struct max98095_cdata *cdata;
-       int sel = ucontrol->value.integer.value[0];
+       unsigned int sel = ucontrol->value.integer.value[0];
        struct max98095_eq_cfg *coef_set;
        int fs, best, best_val, i;
        int regmask, regsave;
@@ -2016,7 +2016,7 @@ static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol,
        struct max98095_pdata *pdata = max98095->pdata;
        int channel = max98095_get_bq_channel(codec, kcontrol->id.name);
        struct max98095_cdata *cdata;
-       int sel = ucontrol->value.integer.value[0];
+       unsigned int sel = ucontrol->value.integer.value[0];
        struct max98095_biquad_cfg *coef_set;
        int fs, best, best_val, i;
        int regmask, regsave;
index 8460edce1c3b6b5cc90dff481e5588c75e2285ad..84a63c660ab93b48f090e4085048cc0959cc6aa2 100644 (file)
@@ -844,18 +844,15 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
        }
 }
 
-static u64 davinci_pcm_dmamask = DMA_BIT_MASK(32);
-
 static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_pcm *pcm = rtd->pcm;
        int ret;
 
-       if (!card->dev->dma_mask)
-               card->dev->dma_mask = &davinci_pcm_dmamask;
-       if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = davinci_pcm_preallocate_dma_buffer(pcm,
index 9cc5c1f82f093f5b171877e1bd5e5672cf9c46cd..f73c7eff8b237b0d7786cd71005789af12b8c0a3 100644 (file)
@@ -298,14 +298,11 @@ static int fsl_dma_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_pcm *pcm = rtd->pcm;
-       static u64 fsl_dma_dmamask = DMA_BIT_MASK(36);
        int ret;
 
-       if (!card->dev->dma_mask)
-               card->dev->dma_mask = &fsl_dma_dmamask;
-
-       if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = fsl_dma_dmamask;
+       ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(36));
+       if (ret)
+               return ret;
 
        /* Some codecs have separate DAIs for playback and capture, so we
         * should allocate a DMA buffer only for the streams that are valid.
index 34043c55f2a62f048232b09ff2f6165fd3726116..fd5f2fb955f182cdef9458e1ab3280d5072365a1 100644 (file)
@@ -272,18 +272,16 @@ static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
        return 0;
 }
 
-static u64 imx_pcm_dmamask = DMA_BIT_MASK(32);
-
 static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_pcm *pcm = rtd->pcm;
-       int ret = 0;
+       int ret;
+
+       ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
-       if (!card->dev->dma_mask)
-               card->dev->dma_mask = &imx_pcm_dmamask;
-       if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = imx_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_PLAYBACK);
index 46c5b4fdfc5298e61008032fe903c0191f886d31..ca1be1d9dcf0349b608f77367f5330ca7c2c6308 100644 (file)
@@ -62,7 +62,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
        struct device_node *ssi_np, *codec_np;
        struct platform_device *ssi_pdev;
        struct i2c_client *codec_dev;
-       struct imx_sgtl5000_data *data;
+       struct imx_sgtl5000_data *data = NULL;
        int int_port, ext_port;
        int ret;
 
@@ -128,7 +128,7 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
                goto fail;
        }
 
-       data->codec_clk = devm_clk_get(&codec_dev->dev, NULL);
+       data->codec_clk = clk_get(&codec_dev->dev, NULL);
        if (IS_ERR(data->codec_clk)) {
                ret = PTR_ERR(data->codec_clk);
                goto fail;
@@ -172,6 +172,8 @@ static int imx_sgtl5000_probe(struct platform_device *pdev)
        return 0;
 
 fail:
+       if (data && !IS_ERR(data->codec_clk))
+               clk_put(data->codec_clk);
        if (ssi_np)
                of_node_put(ssi_np);
        if (codec_np)
@@ -185,6 +187,7 @@ static int imx_sgtl5000_remove(struct platform_device *pdev)
        struct imx_sgtl5000_data *data = platform_get_drvdata(pdev);
 
        snd_soc_unregister_card(&data->card);
+       clk_put(data->codec_clk);
 
        return 0;
 }
index 2a847ca494b5b4dfe00019d1b10c5ae8eccc817b..8fcf2241674054a8d687ae94598a0b1beed26e8a 100644 (file)
@@ -299,7 +299,6 @@ static struct snd_pcm_ops psc_dma_ops = {
        .hw_params      = psc_dma_hw_params,
 };
 
-static u64 psc_dma_dmamask = DMA_BIT_MASK(32);
 static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
@@ -307,15 +306,14 @@ static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
        struct snd_pcm *pcm = rtd->pcm;
        struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
        size_t size = psc_dma_hardware.buffer_bytes_max;
-       int rc = 0;
+       int rc;
 
        dev_dbg(rtd->platform->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n",
                card, dai, pcm);
 
-       if (!card->dev->dma_mask)
-               card->dev->dma_mask = &psc_dma_dmamask;
-       if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+       rc = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+       if (rc)
+               return rc;
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
index 710059292318878886d00383396413c3ec87c8d1..1d7ef28585e1a4125bb70bc17edd203a7195b422 100644 (file)
@@ -297,19 +297,15 @@ static void jz4740_pcm_free(struct snd_pcm *pcm)
        }
 }
 
-static u64 jz4740_pcm_dmamask = DMA_BIT_MASK(32);
-
 static int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_pcm *pcm = rtd->pcm;
-       int ret = 0;
-
-       if (!card->dev->dma_mask)
-               card->dev->dma_mask = &jz4740_pcm_dmamask;
+       int ret;
 
-       if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = jz4740_pcm_preallocate_dma_buffer(pcm,
index b238434f92b099db8bf3ba613fc596b7006ec96d..3814bb0374857b266747323fd973f37fa71dd4ab 100644 (file)
@@ -59,8 +59,6 @@ static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
        .fifo_size              = 0,
 };
 
-static u64 kirkwood_dma_dmamask = DMA_BIT_MASK(32);
-
 static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
 {
        struct kirkwood_dma_data *priv = dev_id;
@@ -292,10 +290,9 @@ static int kirkwood_dma_new(struct snd_soc_pcm_runtime *rtd)
        struct snd_pcm *pcm = rtd->pcm;
        int ret;
 
-       if (!card->dev->dma_mask)
-               card->dev->dma_mask = &kirkwood_dma_dmamask;
-       if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = kirkwood_dma_preallocate_dma_buffer(pcm,
index c894ff0f25809c997197496e810cc52d0299d40a..f588ee45b4fdd610d21c316f469b81b687da40a9 100644 (file)
@@ -314,16 +314,15 @@ static void nuc900_dma_free_dma_buffers(struct snd_pcm *pcm)
        snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
-static u64 nuc900_pcm_dmamask = DMA_BIT_MASK(32);
 static int nuc900_dma_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_pcm *pcm = rtd->pcm;
+       int ret;
 
-       if (!card->dev->dma_mask)
-               card->dev->dma_mask = &nuc900_pcm_dmamask;
-       if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
                card->dev, 4 * 1024, (4 * 1024) - 1);
index a11405de86e82bda8801e837ec48183093bd99db..b8fa9862e54c4a6c6d99c8d3b88e8204d3cd9d63 100644 (file)
@@ -156,8 +156,6 @@ static struct snd_pcm_ops omap_pcm_ops = {
        .mmap           = omap_pcm_mmap,
 };
 
-static u64 omap_pcm_dmamask = DMA_BIT_MASK(64);
-
 static int omap_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
        int stream)
 {
@@ -202,12 +200,11 @@ static int omap_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_pcm *pcm = rtd->pcm;
-       int ret = 0;
+       int ret;
 
-       if (!card->dev->dma_mask)
-               card->dev->dma_mask = &omap_pcm_dmamask;
-       if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = DMA_BIT_MASK(64);
+       ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(64));
+       if (ret)
+               return ret;
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = omap_pcm_preallocate_dma_buffer(pcm,
index 806da27b8b671ed8596484856ec59f8092c75e8d..d58b09f4f7a426dcba4e7a82c26434161dbe124e 100644 (file)
@@ -87,18 +87,15 @@ static struct snd_pcm_ops pxa2xx_pcm_ops = {
        .mmap           = pxa2xx_pcm_mmap,
 };
 
-static u64 pxa2xx_pcm_dmamask = DMA_BIT_MASK(32);
-
 static int pxa2xx_soc_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_pcm *pcm = rtd->pcm;
-       int ret = 0;
+       int ret;
 
-       if (!card->dev->dma_mask)
-               card->dev->dma_mask = &pxa2xx_pcm_dmamask;
-       if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
index d0740a762963d867bf75cce29d20c15c0a4b5097..283620a97fe7b597d2670bd8c985610f5d1161ba 100644 (file)
@@ -444,8 +444,6 @@ static void s6000_pcm_free(struct snd_pcm *pcm)
        snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
-static u64 s6000_pcm_dmamask = DMA_BIT_MASK(32);
-
 static int s6000_pcm_new(struct snd_soc_pcm_runtime *runtime)
 {
        struct snd_card *card = runtime->card->snd_card;
@@ -456,10 +454,9 @@ static int s6000_pcm_new(struct snd_soc_pcm_runtime *runtime)
        params = snd_soc_dai_get_dma_data(runtime->cpu_dai,
                        pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
 
-       if (!card->dev->dma_mask)
-               card->dev->dma_mask = &s6000_pcm_dmamask;
-       if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+       res = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+       if (res)
+               return res;
 
        if (params->dma_in) {
                s6dmac_disable_chan(DMA_MASK_DMAC(params->dma_in),
index 9338d11e92168c222eae4630228f711bd9cf803c..fe2748b494d4cd38c6db6ae4409d38f56819ff3f 100644 (file)
@@ -406,20 +406,17 @@ static void dma_free_dma_buffers(struct snd_pcm *pcm)
        }
 }
 
-static u64 dma_mask = DMA_BIT_MASK(32);
-
 static int dma_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_pcm *pcm = rtd->pcm;
-       int ret = 0;
+       int ret;
 
        pr_debug("Entered %s\n", __func__);
 
-       if (!card->dev->dma_mask)
-               card->dev->dma_mask = &dma_mask;
-       if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = preallocate_dma_buffer(pcm,
index ce1e1e16f250affafbc333d165c2843e043bfa23..e4f318fc2f82bb048f5047a6773f1a2c8be40902 100644 (file)
@@ -383,18 +383,15 @@ static int preallocate_idma_buffer(struct snd_pcm *pcm, int stream)
        return 0;
 }
 
-static u64 idma_mask = DMA_BIT_MASK(32);
-
 static int idma_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_card *card = rtd->card->snd_card;
        struct snd_pcm *pcm = rtd->pcm;
-       int ret = 0;
+       int ret;
 
-       if (!card->dev->dma_mask)
-               card->dev->dma_mask = &idma_mask;
-       if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+       ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = preallocate_idma_buffer(pcm,
index 4d0561312f3be0a9f383928b3d74f80a44cdd3b3..1a38be0d0ca8fbf0724bbec4087569ee418d39a2 100644 (file)
@@ -1380,7 +1380,6 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
                                return -ENODEV;
 
                        list_add(&cpu_dai->dapm.list, &card->dapm_list);
-                       snd_soc_dapm_new_dai_widgets(&cpu_dai->dapm, cpu_dai);
                }
 
                if (cpu_dai->driver->probe) {
index 099e7cd022e46d47260103b226b3410beac27133..7c43479623537af4f0d4179f4cce195cbea3e9b1 100644 (file)
@@ -5,7 +5,6 @@
 #include <stdbool.h>
 #include <sys/vfs.h>
 #include <sys/mount.h>
-#include <linux/magic.h>
 #include <linux/kernel.h>
 
 #include "debugfs.h"
index 15130b50dfe3be2fea6a975a102283f6d33e4887..fe9b61e322a557b063ecc78eccb9a87c8de73dda 100644 (file)
@@ -2,3 +2,6 @@ ifndef NO_DWARF
 PERF_HAVE_DWARF_REGS := 1
 LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
 endif
+ifndef NO_LIBUNWIND
+LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o
+endif
diff --git a/tools/perf/arch/arm/include/perf_regs.h b/tools/perf/arch/arm/include/perf_regs.h
new file mode 100644 (file)
index 0000000..2a1cfde
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef ARCH_PERF_REGS_H
+#define ARCH_PERF_REGS_H
+
+#include <stdlib.h>
+#include "../../util/types.h"
+#include <asm/perf_regs.h>
+
+#define PERF_REGS_MASK ((1ULL << PERF_REG_ARM_MAX) - 1)
+#define PERF_REG_IP    PERF_REG_ARM_PC
+#define PERF_REG_SP    PERF_REG_ARM_SP
+
+static inline const char *perf_reg_name(int id)
+{
+       switch (id) {
+       case PERF_REG_ARM_R0:
+               return "r0";
+       case PERF_REG_ARM_R1:
+               return "r1";
+       case PERF_REG_ARM_R2:
+               return "r2";
+       case PERF_REG_ARM_R3:
+               return "r3";
+       case PERF_REG_ARM_R4:
+               return "r4";
+       case PERF_REG_ARM_R5:
+               return "r5";
+       case PERF_REG_ARM_R6:
+               return "r6";
+       case PERF_REG_ARM_R7:
+               return "r7";
+       case PERF_REG_ARM_R8:
+               return "r8";
+       case PERF_REG_ARM_R9:
+               return "r9";
+       case PERF_REG_ARM_R10:
+               return "r10";
+       case PERF_REG_ARM_FP:
+               return "fp";
+       case PERF_REG_ARM_IP:
+               return "ip";
+       case PERF_REG_ARM_SP:
+               return "sp";
+       case PERF_REG_ARM_LR:
+               return "lr";
+       case PERF_REG_ARM_PC:
+               return "pc";
+       default:
+               return NULL;
+       }
+
+       return NULL;
+}
+
+#endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/arm/util/unwind.c b/tools/perf/arch/arm/util/unwind.c
new file mode 100644 (file)
index 0000000..da3dc95
--- /dev/null
@@ -0,0 +1,48 @@
+
+#include <errno.h>
+#include <libunwind.h>
+#include "perf_regs.h"
+#include "../../util/unwind.h"
+
+int unwind__arch_reg_id(int regnum)
+{
+       switch (regnum) {
+       case UNW_ARM_R0:
+               return PERF_REG_ARM_R0;
+       case UNW_ARM_R1:
+               return PERF_REG_ARM_R1;
+       case UNW_ARM_R2:
+               return PERF_REG_ARM_R2;
+       case UNW_ARM_R3:
+               return PERF_REG_ARM_R3;
+       case UNW_ARM_R4:
+               return PERF_REG_ARM_R4;
+       case UNW_ARM_R5:
+               return PERF_REG_ARM_R5;
+       case UNW_ARM_R6:
+               return PERF_REG_ARM_R6;
+       case UNW_ARM_R7:
+               return PERF_REG_ARM_R7;
+       case UNW_ARM_R8:
+               return PERF_REG_ARM_R8;
+       case UNW_ARM_R9:
+               return PERF_REG_ARM_R9;
+       case UNW_ARM_R10:
+               return PERF_REG_ARM_R10;
+       case UNW_ARM_R11:
+               return PERF_REG_ARM_FP;
+       case UNW_ARM_R12:
+               return PERF_REG_ARM_IP;
+       case UNW_ARM_R13:
+               return PERF_REG_ARM_SP;
+       case UNW_ARM_R14:
+               return PERF_REG_ARM_LR;
+       case UNW_ARM_R15:
+               return PERF_REG_ARM_PC;
+       default:
+               pr_err("unwind: invalid reg id %d\n", regnum);
+               return -EINVAL;
+       }
+
+       return -EINVAL;
+}
index 9570c2b0f83c580454e2610cb3c07a4d7443ee19..b2519e49424f4c42bb389de846d21c8337773036 100644 (file)
@@ -32,7 +32,7 @@ u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc)
 int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
                             struct perf_tsc_conversion *tc)
 {
-       bool cap_usr_time_zero;
+       bool cap_user_time_zero;
        u32 seq;
        int i = 0;
 
@@ -42,7 +42,7 @@ int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
                tc->time_mult = pc->time_mult;
                tc->time_shift = pc->time_shift;
                tc->time_zero = pc->time_zero;
-               cap_usr_time_zero = pc->cap_usr_time_zero;
+               cap_user_time_zero = pc->cap_user_time_zero;
                rmb();
                if (pc->lock == seq && !(seq & 1))
                        break;
@@ -52,7 +52,7 @@ int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
                }
        }
 
-       if (!cap_usr_time_zero)
+       if (!cap_user_time_zero)
                return -EOPNOTSUPP;
 
        return 0;
index 423875c999b21208a5a6274d0fd47a2fb359ecd8..afe377b2884f740b0c469a367ab3938d99f7df0e 100644 (file)
@@ -321,8 +321,6 @@ found:
        return perf_event__repipe(tool, event_sw, &sample_sw, machine);
 }
 
-extern volatile int session_done;
-
 static void sig_handler(int sig __maybe_unused)
 {
        session_done = 1;
index c2dff9cb1f2ce1ac150401d7b859229beb53998e..9b5f077fee5b1b65a4e51b48ef1af0727b8c134b 100644 (file)
@@ -101,7 +101,7 @@ static int setup_cpunode_map(void)
 
        dir1 = opendir(PATH_SYS_NODE);
        if (!dir1)
-               return -1;
+               return 0;
 
        while ((dent1 = readdir(dir1)) != NULL) {
                if (dent1->d_type != DT_DIR ||
index 8e50d8d77419c7ca3e8ce72209b113d72665c09e..72eae7498c09419c8f1f77a7a005c6dcbbb5eb4b 100644 (file)
@@ -401,8 +401,6 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
        return 0;
 }
 
-extern volatile int session_done;
-
 static void sig_handler(int sig __maybe_unused)
 {
        session_done = 1;
@@ -568,6 +566,9 @@ static int __cmd_report(struct perf_report *rep)
                }
        }
 
+       if (session_done())
+               return 0;
+
        if (nr_samples == 0) {
                ui__error("The %s file has no samples!\n", session->filename);
                return 0;
index 7f31a3ded1b6dc59730a0162d5af279e038d1afc..9c333ff3dfeb3de716eac13d48d7364e998bb50d 100644 (file)
@@ -553,8 +553,6 @@ static struct perf_tool perf_script = {
        .ordering_requires_timestamps = true,
 };
 
-extern volatile int session_done;
-
 static void sig_handler(int sig __maybe_unused)
 {
        session_done = 1;
index f5aa6375e3e9add4eea3cdd81de685fa37d87c4d..71aa3e35406bd064e87044d2ae71597a5f117092 100644 (file)
 #include <sys/mman.h>
 #include <linux/futex.h>
 
+/* For older distros: */
+#ifndef MAP_STACK
+# define MAP_STACK             0x20000
+#endif
+
+#ifndef MADV_HWPOISON
+# define MADV_HWPOISON         100
+#endif
+
+#ifndef MADV_MERGEABLE
+# define MADV_MERGEABLE                12
+#endif
+
+#ifndef MADV_UNMERGEABLE
+# define MADV_UNMERGEABLE      13
+#endif
+
 static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
                                         unsigned long arg,
                                         u8 arg_idx __maybe_unused,
@@ -1038,6 +1055,7 @@ static int trace__replay(struct trace *trace)
 
        trace->tool.sample        = trace__process_sample;
        trace->tool.mmap          = perf_event__process_mmap;
+       trace->tool.mmap2         = perf_event__process_mmap2;
        trace->tool.comm          = perf_event__process_comm;
        trace->tool.exit          = perf_event__process_exit;
        trace->tool.fork          = perf_event__process_fork;
index 214e17e97e5c7ba5aa25545b465b8994ac666afc..75b93d7f786010000368e299d214717131c67fa1 100644 (file)
@@ -29,6 +29,10 @@ ifeq ($(ARCH),x86_64)
   NO_PERF_REGS := 0
   LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
 endif
+ifeq ($(ARCH),arm)
+  NO_PERF_REGS := 0
+  LIBUNWIND_LIBS = -lunwind -lunwind-arm
+endif
 
 ifeq ($(NO_PERF_REGS),0)
   CFLAGS += -DHAVE_PERF_REGS
@@ -87,7 +91,7 @@ CFLAGS += -Wall
 CFLAGS += -Wextra
 CFLAGS += -std=gnu99
 
-EXTLIBS = -lelf -lpthread -lrt -lm
+EXTLIBS = -lelf -lpthread -lrt -lm -ldl
 
 ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y)
   CFLAGS += -fstack-protector-all
@@ -180,6 +184,9 @@ FLAGS_LIBELF=$(CFLAGS) $(LDFLAGS) $(EXTLIBS)
 ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_LIBELF),-DLIBELF_MMAP),y)
   CFLAGS += -DLIBELF_MMAP
 endif
+ifeq ($(call try-cc,$(SOURCE_ELF_GETPHDRNUM),$(FLAGS_LIBELF),-DHAVE_ELF_GETPHDRNUM),y)
+  CFLAGS += -DHAVE_ELF_GETPHDRNUM
+endif
 
 # include ARCH specific config
 -include $(src-perf)/arch/$(ARCH)/Makefile
@@ -205,8 +212,7 @@ ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_LIBELF),-DLIBELF_MMAP),y)
 endif # try-cc
 endif # NO_LIBELF
 
-# There's only x86 (both 32 and 64) support for CFI unwind so far
-ifneq ($(ARCH),x86)
+ifeq ($(LIBUNWIND_LIBS),)
   NO_LIBUNWIND := 1
 endif
 
@@ -220,9 +226,13 @@ endif
 
 FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(CFLAGS) $(LIBUNWIND_LDFLAGS) $(LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS)
 ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND),libunwind),y)
-  msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 0.99);
+  msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 1.1);
   NO_LIBUNWIND := 1
 endif # Libunwind support
+ifneq ($(call try-cc,$(SOURCE_LIBUNWIND_DEBUG_FRAME),$(FLAGS_UNWIND),libunwind debug_frame),y)
+  msg := $(warning No debug_frame support found in libunwind);
+CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME
+endif # debug_frame support in libunwind
 endif # NO_LIBUNWIND
 
 ifndef NO_LIBUNWIND
index 708fb8e9822a3ed43bd192470c5da6f01c236c38..40b21c0bc10a1bcc99d9086acafab89e3813b80f 100644 (file)
@@ -61,6 +61,15 @@ int main(void)
 }
 endef
 
+define SOURCE_ELF_GETPHDRNUM
+#include <libelf.h>
+int main(void)
+{
+       size_t dst;
+       return elf_getphdrnum(0, &dst);
+}
+endef
+
 ifndef NO_SLANG
 define SOURCE_SLANG
 #include <slang.h>
@@ -176,7 +185,6 @@ extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
                                       unw_proc_info_t *pi,
                                       int need_unwind_info, void *arg);
 
-
 #define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
 
 int main(void)
@@ -188,6 +196,26 @@ int main(void)
        return 0;
 }
 endef
+
+define SOURCE_LIBUNWIND_DEBUG_FRAME
+#include <libunwind.h>
+#include <stdlib.h>
+
+extern int
+UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
+                                unw_word_t ip, unw_word_t segbase,
+                                const char *obj_name, unw_word_t start,
+                                unw_word_t end);
+
+#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
+
+int main(void)
+{
+       dwarf_find_debug_frame(0, NULL, 0, 0, NULL, 0, 0);
+       return 0;
+}
+endef
+
 endif
 
 ifndef NO_BACKTRACE
@@ -210,6 +238,7 @@ define SOURCE_LIBAUDIT
 
 int main(void)
 {
+       printf(\"error message: %s\n\", audit_errno_to_name(0));
        return audit_open();
 }
 endef
index bfc5a27597d60e1f09b7f95ef691e37608f8c694..7eae5488ecea47344cac10677104cb9e6cb2cc44 100644 (file)
@@ -809,7 +809,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
                    end = map__rip_2objdump(map, sym->end);
 
                offset = line_ip - start;
-               if (offset < 0 || (u64)line_ip > end)
+               if ((u64)line_ip < start || (u64)line_ip > end)
                        offset = -1;
                else
                        parsed_line = tmp2 + 1;
index 3e5f5430a28aa929741e2bd3ccbcf554ae62a074..e23bde19d590872c6567c35d0df39fd5d0d68a87 100644 (file)
@@ -262,6 +262,21 @@ bool die_is_signed_type(Dwarf_Die *tp_die)
                ret == DW_ATE_signed_fixed);
 }
 
+/**
+ * die_is_func_def - Ensure that this DIE is a subprogram and definition
+ * @dw_die: a DIE
+ *
+ * Ensure that this DIE is a subprogram and NOT a declaration. This
+ * returns true if @dw_die is a function definition.
+ **/
+bool die_is_func_def(Dwarf_Die *dw_die)
+{
+       Dwarf_Attribute attr;
+
+       return (dwarf_tag(dw_die) == DW_TAG_subprogram &&
+               dwarf_attr(dw_die, DW_AT_declaration, &attr) == NULL);
+}
+
 /**
  * die_get_data_member_location - Get the data-member offset
  * @mb_die: a DIE of a member of a data structure
@@ -392,6 +407,10 @@ static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
 {
        struct __addr_die_search_param *ad = data;
 
+       /*
+        * Since a declaration entry doesn't has given pc, this always returns
+        * function definition entry.
+        */
        if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
            dwarf_haspc(fn_die, ad->addr)) {
                memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
index 6ce1717784b7ab42a14d58431c3026df749f0620..8658d41697d27fbbe06dbd1fbdbc3b9d895b4606 100644 (file)
@@ -38,6 +38,9 @@ extern int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
 extern int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
                        int (*callback)(Dwarf_Die *, void *), void *data);
 
+/* Ensure that this DIE is a subprogram and definition (not declaration) */
+extern bool die_is_func_def(Dwarf_Die *dw_die);
+
 /* Compare diename and tname */
 extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname);
 
index 26441d0e571bfce2bcd469dfdfe428175facb5ee..ce69901176d864506d39cc0df4f5dbe9479f9383 100644 (file)
@@ -199,9 +199,11 @@ static int write_buildid(char *name, size_t name_len, u8 *build_id,
        return write_padded(fd, name, name_len + 1, len);
 }
 
-static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
-                               u16 misc, int fd)
+static int __dsos__write_buildid_table(struct list_head *head,
+                                      struct machine *machine,
+                                      pid_t pid, u16 misc, int fd)
 {
+       char nm[PATH_MAX];
        struct dso *pos;
 
        dsos__for_each_with_build_id(pos, head) {
@@ -215,6 +217,10 @@ static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
                if (is_vdso_map(pos->short_name)) {
                        name = (char *) VDSO__MAP_NAME;
                        name_len = sizeof(VDSO__MAP_NAME) + 1;
+               } else if (dso__is_kcore(pos)) {
+                       machine__mmap_name(machine, nm, sizeof(nm));
+                       name = nm;
+                       name_len = strlen(nm) + 1;
                } else {
                        name = pos->long_name;
                        name_len = pos->long_name_len + 1;
@@ -240,10 +246,10 @@ static int machine__write_buildid_table(struct machine *machine, int fd)
                umisc = PERF_RECORD_MISC_GUEST_USER;
        }
 
-       err = __dsos__write_buildid_table(&machine->kernel_dsos, machine->pid,
-                                         kmisc, fd);
+       err = __dsos__write_buildid_table(&machine->kernel_dsos, machine,
+                                         machine->pid, kmisc, fd);
        if (err == 0)
-               err = __dsos__write_buildid_table(&machine->user_dsos,
+               err = __dsos__write_buildid_table(&machine->user_dsos, machine,
                                                  machine->pid, umisc, fd);
        return err;
 }
@@ -375,23 +381,31 @@ out_free:
        return err;
 }
 
-static int dso__cache_build_id(struct dso *dso, const char *debugdir)
+static int dso__cache_build_id(struct dso *dso, struct machine *machine,
+                              const char *debugdir)
 {
        bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
        bool is_vdso = is_vdso_map(dso->short_name);
+       char *name = dso->long_name;
+       char nm[PATH_MAX];
 
-       return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id),
-                                    dso->long_name, debugdir,
-                                    is_kallsyms, is_vdso);
+       if (dso__is_kcore(dso)) {
+               is_kallsyms = true;
+               machine__mmap_name(machine, nm, sizeof(nm));
+               name = nm;
+       }
+       return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
+                                    debugdir, is_kallsyms, is_vdso);
 }
 
-static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
+static int __dsos__cache_build_ids(struct list_head *head,
+                                  struct machine *machine, const char *debugdir)
 {
        struct dso *pos;
        int err = 0;
 
        dsos__for_each_with_build_id(pos, head)
-               if (dso__cache_build_id(pos, debugdir))
+               if (dso__cache_build_id(pos, machine, debugdir))
                        err = -1;
 
        return err;
@@ -399,8 +413,9 @@ static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
 
 static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
 {
-       int ret = __dsos__cache_build_ids(&machine->kernel_dsos, debugdir);
-       ret |= __dsos__cache_build_ids(&machine->user_dsos, debugdir);
+       int ret = __dsos__cache_build_ids(&machine->kernel_dsos, machine,
+                                         debugdir);
+       ret |= __dsos__cache_build_ids(&machine->user_dsos, machine, debugdir);
        return ret;
 }
 
index 46a0d35a05e1f21aae097e7a67cea89bfe9ecddf..9ff6cf3e9a99f69596b37372f60203c11bec88a3 100644 (file)
@@ -611,6 +611,8 @@ void hists__collapse_resort(struct hists *hists)
        next = rb_first(root);
 
        while (next) {
+               if (session_done())
+                       break;
                n = rb_entry(next, struct hist_entry, rb_node_in);
                next = rb_next(&n->rb_node_in);
 
index 933d14f287ca92645152f7714651a10b818e87bc..6188d2876a7128aaa68e426c3334dfcae099dc41 100644 (file)
@@ -792,7 +792,7 @@ static int machine__create_modules(struct machine *machine)
                modules = path;
        }
 
-       if (symbol__restricted_filename(path, "/proc/modules"))
+       if (symbol__restricted_filename(modules, "/proc/modules"))
                return -1;
 
        file = fopen(modules, "r");
index be0329394d5639f77644d8a9079dd6ceb4f27a73..371476cb8ddc17a6643a6298ba887f8c6aa75bcb 100644 (file)
@@ -118,7 +118,6 @@ static const Dwfl_Callbacks offline_callbacks = {
 static int debuginfo__init_offline_dwarf(struct debuginfo *self,
                                         const char *path)
 {
-       Dwfl_Module *mod;
        int fd;
 
        fd = open(path, O_RDONLY);
@@ -129,11 +128,11 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *self,
        if (!self->dwfl)
                goto error;
 
-       mod = dwfl_report_offline(self->dwfl, "", "", fd);
-       if (!mod)
+       self->mod = dwfl_report_offline(self->dwfl, "", "", fd);
+       if (!self->mod)
                goto error;
 
-       self->dbg = dwfl_module_getdwarf(mod, &self->bias);
+       self->dbg = dwfl_module_getdwarf(self->mod, &self->bias);
        if (!self->dbg)
                goto error;
 
@@ -676,37 +675,42 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
 }
 
 /* Convert subprogram DIE to trace point */
-static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
-                                 bool retprobe, struct probe_trace_point *tp)
+static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
+                                 Dwarf_Addr paddr, bool retprobe,
+                                 struct probe_trace_point *tp)
 {
        Dwarf_Addr eaddr, highaddr;
-       const char *name;
-
-       /* Copy the name of probe point */
-       name = dwarf_diename(sp_die);
-       if (name) {
-               if (dwarf_entrypc(sp_die, &eaddr) != 0) {
-                       pr_warning("Failed to get entry address of %s\n",
-                                  dwarf_diename(sp_die));
-                       return -ENOENT;
-               }
-               if (dwarf_highpc(sp_die, &highaddr) != 0) {
-                       pr_warning("Failed to get end address of %s\n",
-                                  dwarf_diename(sp_die));
-                       return -ENOENT;
-               }
-               if (paddr > highaddr) {
-                       pr_warning("Offset specified is greater than size of %s\n",
-                                  dwarf_diename(sp_die));
-                       return -EINVAL;
-               }
-               tp->symbol = strdup(name);
-               if (tp->symbol == NULL)
-                       return -ENOMEM;
-               tp->offset = (unsigned long)(paddr - eaddr);
-       } else
-               /* This function has no name. */
-               tp->offset = (unsigned long)paddr;
+       GElf_Sym sym;
+       const char *symbol;
+
+       /* Verify the address is correct */
+       if (dwarf_entrypc(sp_die, &eaddr) != 0) {
+               pr_warning("Failed to get entry address of %s\n",
+                          dwarf_diename(sp_die));
+               return -ENOENT;
+       }
+       if (dwarf_highpc(sp_die, &highaddr) != 0) {
+               pr_warning("Failed to get end address of %s\n",
+                          dwarf_diename(sp_die));
+               return -ENOENT;
+       }
+       if (paddr > highaddr) {
+               pr_warning("Offset specified is greater than size of %s\n",
+                          dwarf_diename(sp_die));
+               return -EINVAL;
+       }
+
+       /* Get an appropriate symbol from symtab */
+       symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
+       if (!symbol) {
+               pr_warning("Failed to find symbol at 0x%lx\n",
+                          (unsigned long)paddr);
+               return -ENOENT;
+       }
+       tp->offset = (unsigned long)(paddr - sym.st_value);
+       tp->symbol = strdup(symbol);
+       if (!tp->symbol)
+               return -ENOMEM;
 
        /* Return probe must be on the head of a subprogram */
        if (retprobe) {
@@ -734,7 +738,7 @@ static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
        }
 
        /* If not a real subprogram, find a real one */
-       if (dwarf_tag(sc_die) != DW_TAG_subprogram) {
+       if (!die_is_func_def(sc_die)) {
                if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
                        pr_warning("Failed to find probe point in any "
                                   "functions.\n");
@@ -980,12 +984,10 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
        struct dwarf_callback_param *param = data;
        struct probe_finder *pf = param->data;
        struct perf_probe_point *pp = &pf->pev->point;
-       Dwarf_Attribute attr;
 
        /* Check tag and diename */
-       if (dwarf_tag(sp_die) != DW_TAG_subprogram ||
-           !die_compare_name(sp_die, pp->function) ||
-           dwarf_attr(sp_die, DW_AT_declaration, &attr))
+       if (!die_is_func_def(sp_die) ||
+           !die_compare_name(sp_die, pp->function))
                return DWARF_CB_OK;
 
        /* Check declared file */
@@ -1151,7 +1153,7 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
        tev = &tf->tevs[tf->ntevs++];
 
        /* Trace point should be converted from subprogram DIE */
-       ret = convert_to_trace_point(&pf->sp_die, pf->addr,
+       ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr,
                                     pf->pev->point.retprobe, &tev->point);
        if (ret < 0)
                return ret;
@@ -1183,7 +1185,7 @@ int debuginfo__find_trace_events(struct debuginfo *self,
 {
        struct trace_event_finder tf = {
                        .pf = {.pev = pev, .callback = add_probe_trace_event},
-                       .max_tevs = max_tevs};
+                       .mod = self->mod, .max_tevs = max_tevs};
        int ret;
 
        /* Allocate result tevs array */
@@ -1252,7 +1254,7 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
        vl = &af->vls[af->nvls++];
 
        /* Trace point should be converted from subprogram DIE */
-       ret = convert_to_trace_point(&pf->sp_die, pf->addr,
+       ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr,
                                     pf->pev->point.retprobe, &vl->point);
        if (ret < 0)
                return ret;
@@ -1291,6 +1293,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *self,
 {
        struct available_var_finder af = {
                        .pf = {.pev = pev, .callback = add_available_vars},
+                       .mod = self->mod,
                        .max_vls = max_vls, .externs = externs};
        int ret;
 
@@ -1474,7 +1477,7 @@ static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
        return 0;
 }
 
-/* Search function from function name */
+/* Search function definition from function name */
 static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
 {
        struct dwarf_callback_param *param = data;
@@ -1485,7 +1488,7 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
        if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die)))
                return DWARF_CB_OK;
 
-       if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
+       if (die_is_func_def(sp_die) &&
            die_compare_name(sp_die, lr->function)) {
                lf->fname = dwarf_decl_file(sp_die);
                dwarf_decl_line(sp_die, &lr->offset);
index 17e94d0c36f981dbf8dbc245410b9a4aa511d16c..3b7d63018960d7ff6a6808ce81eff2d34b40bd09 100644 (file)
@@ -23,6 +23,7 @@ static inline int is_c_varname(const char *name)
 /* debug information structure */
 struct debuginfo {
        Dwarf           *dbg;
+       Dwfl_Module     *mod;
        Dwfl            *dwfl;
        Dwarf_Addr      bias;
 };
@@ -77,6 +78,7 @@ struct probe_finder {
 
 struct trace_event_finder {
        struct probe_finder     pf;
+       Dwfl_Module             *mod;           /* For solving symbols */
        struct probe_trace_event *tevs;         /* Found trace events */
        int                     ntevs;          /* Number of trace events */
        int                     max_tevs;       /* Max number of trace events */
@@ -84,6 +86,7 @@ struct trace_event_finder {
 
 struct available_var_finder {
        struct probe_finder     pf;
+       Dwfl_Module             *mod;           /* For solving symbols */
        struct variable_list    *vls;           /* Found variable lists */
        int                     nvls;           /* Number of variable lists */
        int                     max_vls;        /* Max no. of variable lists */
index 51f5edf2a6d0d140dd897c58f9d606c9fb25be9d..70ffa41518f34a1bbfaa82e67c46a8a22b133f67 100644 (file)
@@ -531,6 +531,9 @@ static int flush_sample_queue(struct perf_session *s,
                return 0;
 
        list_for_each_entry_safe(iter, tmp, head, list) {
+               if (session_done())
+                       return 0;
+
                if (iter->timestamp > limit)
                        break;
 
@@ -1160,7 +1163,6 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
        }
 }
 
-#define session_done() (*(volatile int *)(&session_done))
 volatile int session_done;
 
 static int __perf_session__process_pipe_events(struct perf_session *self,
@@ -1372,10 +1374,13 @@ more:
                                    "Processing events...");
        }
 
+       err = 0;
+       if (session_done())
+               goto out_err;
+
        if (file_pos < file_size)
                goto more;
 
-       err = 0;
        /* do the final flush for ordered samples */
        session->ordered_samples.next_flush = ULLONG_MAX;
        err = flush_sample_queue(session, tool);
index 3aa75fb2225f7129daa12f7e86219f30928e5e42..04bf7373a7e5fb04222b1a9cdb5c295045c0626f 100644 (file)
@@ -124,4 +124,8 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
 
 #define perf_session__set_tracepoints_handlers(session, array) \
        __perf_session__set_tracepoints_handlers(session, array, ARRAY_SIZE(array))
+
+extern volatile int session_done;
+
+#define session_done() (*(volatile int *)(&session_done))
 #endif /* __PERF_SESSION_H */
index a7b9ab55738086c24d12d7e9ee8cb6143ffd47aa..a9c829be52169eac5b9f00d9382fd9281152b9e6 100644 (file)
@@ -8,6 +8,22 @@
 #include "symbol.h"
 #include "debug.h"
 
+#ifndef HAVE_ELF_GETPHDRNUM
+static int elf_getphdrnum(Elf *elf, size_t *dst)
+{
+       GElf_Ehdr gehdr;
+       GElf_Ehdr *ehdr;
+
+       ehdr = gelf_getehdr(elf, &gehdr);
+       if (!ehdr)
+               return -1;
+
+       *dst = ehdr->e_phnum;
+
+       return 0;
+}
+#endif
+
 #ifndef NT_GNU_BUILD_ID
 #define NT_GNU_BUILD_ID 3
 #endif
index fe7a27d67d2b7af23a596683509769a4f1bd6e38..e9e1c03f927d27bce1e041a9cc61ca47dae2b987 100644 (file)
@@ -186,7 +186,7 @@ void parse_proc_kallsyms(struct pevent *pevent,
        char *next = NULL;
        char *addr_str;
        char *mod;
-       char *fmt;
+       char *fmt = NULL;
 
        line = strtok_r(file, "\n", &next);
        while (line) {
index 2f891f7e70bf9251c849780ec008ded14a2776c9..5390d0b8862a680e147cf52dd8bed22cfbba333f 100644 (file)
@@ -39,6 +39,15 @@ UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
 
 #define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
 
+extern int
+UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
+                                unw_word_t ip,
+                                unw_word_t segbase,
+                                const char *obj_name, unw_word_t start,
+                                unw_word_t end);
+
+#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
+
 #define DW_EH_PE_FORMAT_MASK   0x0f    /* format of the encoded value */
 #define DW_EH_PE_APPL_MASK     0x70    /* how the value is to be applied */
 
@@ -245,8 +254,9 @@ static int unwind_spec_ehframe(struct dso *dso, struct machine *machine,
        return 0;
 }
 
-static int read_unwind_spec(struct dso *dso, struct machine *machine,
-                           u64 *table_data, u64 *segbase, u64 *fde_count)
+static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
+                                    u64 *table_data, u64 *segbase,
+                                    u64 *fde_count)
 {
        int ret = -EINVAL, fd;
        u64 offset;
@@ -255,6 +265,7 @@ static int read_unwind_spec(struct dso *dso, struct machine *machine,
        if (fd < 0)
                return -EINVAL;
 
+       /* Check the .eh_frame section for unwinding info */
        offset = elf_section_offset(fd, ".eh_frame_hdr");
        close(fd);
 
@@ -263,10 +274,29 @@ static int read_unwind_spec(struct dso *dso, struct machine *machine,
                                          table_data, segbase,
                                          fde_count);
 
-       /* TODO .debug_frame check if eh_frame_hdr fails */
        return ret;
 }
 
+#ifndef NO_LIBUNWIND_DEBUG_FRAME
+static int read_unwind_spec_debug_frame(struct dso *dso,
+                                       struct machine *machine, u64 *offset)
+{
+       int fd = dso__data_fd(dso, machine);
+
+       if (fd < 0)
+               return -EINVAL;
+
+       /* Check the .debug_frame section for unwinding info */
+       *offset = elf_section_offset(fd, ".debug_frame");
+       close(fd);
+
+       if (*offset)
+               return 0;
+
+       return -EINVAL;
+}
+#endif
+
 static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
 {
        struct addr_location al;
@@ -291,20 +321,33 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
 
        pr_debug("unwind: find_proc_info dso %s\n", map->dso->name);
 
-       if (read_unwind_spec(map->dso, ui->machine,
-                            &table_data, &segbase, &fde_count))
-               return -EINVAL;
+       /* Check the .eh_frame section for unwinding info */
+       if (!read_unwind_spec_eh_frame(map->dso, ui->machine,
+                                      &table_data, &segbase, &fde_count)) {
+               memset(&di, 0, sizeof(di));
+               di.format   = UNW_INFO_FORMAT_REMOTE_TABLE;
+               di.start_ip = map->start;
+               di.end_ip   = map->end;
+               di.u.rti.segbase    = map->start + segbase;
+               di.u.rti.table_data = map->start + table_data;
+               di.u.rti.table_len  = fde_count * sizeof(struct table_entry)
+                                     / sizeof(unw_word_t);
+               return dwarf_search_unwind_table(as, ip, &di, pi,
+                                                need_unwind_info, arg);
+       }
+
+#ifndef NO_LIBUNWIND_DEBUG_FRAME
+       /* Check the .debug_frame section for unwinding info */
+       if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) {
+               memset(&di, 0, sizeof(di));
+               dwarf_find_debug_frame(0, &di, ip, 0, map->dso->name,
+                                      map->start, map->end);
+               return dwarf_search_unwind_table(as, ip, &di, pi,
+                                                need_unwind_info, arg);
+       }
+#endif
 
-       memset(&di, 0, sizeof(di));
-       di.format   = UNW_INFO_FORMAT_REMOTE_TABLE;
-       di.start_ip = map->start;
-       di.end_ip   = map->end;
-       di.u.rti.segbase    = map->start + segbase;
-       di.u.rti.table_data = map->start + table_data;
-       di.u.rti.table_len  = fde_count * sizeof(struct table_entry)
-                             / sizeof(unw_word_t);
-       return dwarf_search_unwind_table(as, ip, &di, pi,
-                                        need_unwind_info, arg);
+       return -EINVAL;
 }
 
 static int access_fpreg(unw_addr_space_t __maybe_unused as,
index ea475cd035112a9db93ffa028a552df9be0724af..8a39dda7a3254677df5996c07c965a2f9f5ef8a8 100644 (file)
@@ -101,8 +101,11 @@ void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu)
                                   typeof(*work), queue);
                cancel_work_sync(&work->work);
                list_del(&work->queue);
-               if (!work->done) /* work was canceled */
+               if (!work->done) { /* work was canceled */
+                       mmdrop(work->mm);
+                       kvm_put_kvm(vcpu->kvm); /* == work->vcpu->kvm */
                        kmem_cache_free(async_pf_cache, work);
+               }
        }
 
        spin_lock(&vcpu->async_pf.lock);
index bf040c4e02b332b7dd2126ae6ed2013261ecfdb4..a9dd682cf5e3f5117de017156396337a8352914f 100644 (file)
@@ -1058,12 +1058,18 @@ unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn)
 EXPORT_SYMBOL_GPL(gfn_to_hva);
 
 /*
- * The hva returned by this function is only allowed to be read.
- * It should pair with kvm_read_hva() or kvm_read_hva_atomic().
+ * If writable is set to false, the hva returned by this function is only
+ * allowed to be read.
  */
-static unsigned long gfn_to_hva_read(struct kvm *kvm, gfn_t gfn)
+unsigned long gfn_to_hva_prot(struct kvm *kvm, gfn_t gfn, bool *writable)
 {
-       return __gfn_to_hva_many(gfn_to_memslot(kvm, gfn), gfn, NULL, false);
+       struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn);
+       unsigned long hva = __gfn_to_hva_many(slot, gfn, NULL, false);
+
+       if (!kvm_is_error_hva(hva) && writable)
+               *writable = !memslot_is_readonly(slot);
+
+       return hva;
 }
 
 static int kvm_read_hva(void *data, void __user *hva, int len)
@@ -1430,7 +1436,7 @@ int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset,
        int r;
        unsigned long addr;
 
-       addr = gfn_to_hva_read(kvm, gfn);
+       addr = gfn_to_hva_prot(kvm, gfn, NULL);
        if (kvm_is_error_hva(addr))
                return -EFAULT;
        r = kvm_read_hva(data, (void __user *)addr + offset, len);
@@ -1468,7 +1474,7 @@ int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data,
        gfn_t gfn = gpa >> PAGE_SHIFT;
        int offset = offset_in_page(gpa);
 
-       addr = gfn_to_hva_read(kvm, gfn);
+       addr = gfn_to_hva_prot(kvm, gfn, NULL);
        if (kvm_is_error_hva(addr))
                return -EFAULT;
        pagefault_disable();