]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge tag 'edac_for_3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 2 Jun 2014 15:59:46 +0000 (08:59 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 2 Jun 2014 15:59:46 +0000 (08:59 -0700)
Pull EDAC changes from Borislav Petkov:
 "Just two small fixlets.

  We have more in the pipe but we didn't get ready in time so more stuff
  next time"

* tag 'edac_for_3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp:
  EDAC: Fix MC scrub mode comparsion bug for correctable errors
  EDAC, MCE, AMD: Remove leftover unused mask

924 files changed:
Documentation/ABI/testing/sysfs-bus-pci
Documentation/DocBook/drm.tmpl
Documentation/DocBook/media/Makefile
Documentation/acpi/enumeration.txt
Documentation/debugging-via-ohci1394.txt
Documentation/device-mapper/thin-provisioning.txt
Documentation/devicetree/bindings/clock/at91-clock.txt
Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
Documentation/devicetree/bindings/dma/ti-edma.txt
Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt
Documentation/devicetree/bindings/net/arc_emac.txt
Documentation/devicetree/bindings/net/mdio-gpio.txt
Documentation/driver-model/devres.txt
Documentation/email-clients.txt
Documentation/filesystems/proc.txt
Documentation/gpio/driver.txt
Documentation/hwmon/sysfs-interface
Documentation/input/elantech.txt
Documentation/java.txt
Documentation/kernel-parameters.txt
Documentation/networking/filter.txt
Documentation/networking/packet_mmap.txt
Documentation/networking/scaling.txt
Documentation/virtual/kvm/api.txt
MAINTAINERS
Makefile
arch/arm/boot/dts/am33xx.dtsi
arch/arm/boot/dts/am3517.dtsi
arch/arm/boot/dts/am437x-gp-evm.dts
arch/arm/boot/dts/armada-370-db.dts
arch/arm/boot/dts/armada-375-db.dts
arch/arm/boot/dts/armada-380.dtsi
arch/arm/boot/dts/armada-385.dtsi
arch/arm/boot/dts/armada-xp-db.dts
arch/arm/boot/dts/armada-xp-gp.dts
arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
arch/arm/boot/dts/at91-sama5d3_xplained.dts
arch/arm/boot/dts/at91sam9260.dtsi
arch/arm/boot/dts/at91sam9261.dtsi
arch/arm/boot/dts/at91sam9rl.dtsi
arch/arm/boot/dts/exynos4412-trats2.dts
arch/arm/boot/dts/exynos5250-arndale.dts
arch/arm/boot/dts/exynos5420-arndale-octa.dts
arch/arm/boot/dts/exynos5420.dtsi
arch/arm/boot/dts/imx53-mba53.dts
arch/arm/boot/dts/imx53.dtsi
arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts
arch/arm/boot/dts/kirkwood-nsa310-common.dtsi
arch/arm/boot/dts/kirkwood-t5325.dts
arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi
arch/arm/boot/dts/omap2.dtsi
arch/arm/boot/dts/omap2420.dtsi
arch/arm/boot/dts/omap2430.dtsi
arch/arm/boot/dts/omap3-cm-t3x30.dtsi
arch/arm/boot/dts/omap3-igep.dtsi
arch/arm/boot/dts/omap3-igep0020.dts
arch/arm/boot/dts/omap3-sb-t35.dtsi
arch/arm/boot/dts/omap3-sbc-t3517.dts
arch/arm/boot/dts/omap3.dtsi
arch/arm/boot/dts/omap5.dtsi
arch/arm/boot/dts/sama5d3.dtsi
arch/arm/boot/dts/sama5d3_mci2.dtsi
arch/arm/boot/dts/sama5d3_tcb1.dtsi
arch/arm/boot/dts/sama5d3_uart.dtsi
arch/arm/boot/dts/ste-ccu8540.dts
arch/arm/boot/dts/sun7i-a20.dtsi
arch/arm/common/bL_switcher.c
arch/arm/common/edma.c
arch/arm/configs/exynos_defconfig
arch/arm/configs/sunxi_defconfig
arch/arm/include/asm/trusted_foundations.h
arch/arm/include/asm/uaccess.h
arch/arm/include/asm/xen/hypercall.h
arch/arm/include/asm/xen/interface.h
arch/arm/include/asm/xen/page.h
arch/arm/kernel/entry-header.S
arch/arm/kernel/unwind.c
arch/arm/mach-at91/at91sam9260_devices.c
arch/arm/mach-exynos/firmware.c
arch/arm/mach-imx/devices/platform-ipu-core.c
arch/arm/mach-mvebu/mvebu-soc-id.c
arch/arm/mach-omap2/board-flash.c
arch/arm/mach-omap2/cclock3xxx_data.c
arch/arm/mach-omap2/cpuidle44xx.c
arch/arm/mach-omap2/omap-headsmp.S
arch/arm/mach-omap2/omap_hwmod_54xx_data.c
arch/arm/mach-orion5x/common.h
arch/arm/mm/proc-v7m.S
arch/arm/plat-omap/dma.c
arch/arm/xen/enlighten.c
arch/arm/xen/hypercall.S
arch/arm64/include/asm/memory.h
arch/arm64/include/asm/pgtable.h
arch/arm64/kernel/irq.c
arch/arm64/mm/hugetlbpage.c
arch/arm64/xen/hypercall.S
arch/ia64/include/asm/unistd.h
arch/ia64/include/uapi/asm/unistd.h
arch/ia64/kernel/entry.S
arch/m68k/Kconfig.debug
arch/m68k/amiga/amisound.c
arch/m68k/amiga/config.c
arch/m68k/apollo/config.c
arch/m68k/atari/stram.c
arch/m68k/configs/amiga_defconfig
arch/m68k/configs/apollo_defconfig
arch/m68k/configs/atari_defconfig
arch/m68k/configs/bvme6000_defconfig
arch/m68k/configs/hp300_defconfig
arch/m68k/configs/mac_defconfig
arch/m68k/configs/multi_defconfig
arch/m68k/configs/mvme147_defconfig
arch/m68k/configs/mvme16x_defconfig
arch/m68k/configs/q40_defconfig
arch/m68k/configs/sun3_defconfig
arch/m68k/configs/sun3x_defconfig
arch/m68k/hp300/config.c
arch/m68k/include/asm/atari_stram.h
arch/m68k/include/asm/unistd.h
arch/m68k/include/uapi/asm/unistd.h
arch/m68k/kernel/Makefile
arch/m68k/kernel/early_printk.c [new file with mode: 0644]
arch/m68k/kernel/head.S
arch/m68k/kernel/syscalltable.S
arch/m68k/mac/config.c
arch/m68k/mm/motorola.c
arch/m68k/mvme16x/config.c
arch/metag/include/asm/barrier.h
arch/metag/include/asm/processor.h
arch/metag/include/uapi/asm/Kbuild
arch/metag/include/uapi/asm/resource.h [deleted file]
arch/mips/Makefile
arch/mips/dec/ecc-berr.c
arch/mips/dec/kn02xa-berr.c
arch/mips/dec/prom/Makefile
arch/mips/dec/prom/call_o32.S [deleted file]
arch/mips/fw/lib/call_o32.S
arch/mips/fw/sni/sniprom.c
arch/mips/include/asm/cpu-info.h
arch/mips/include/asm/dec/prom.h
arch/mips/include/asm/rm9k-ocd.h [deleted file]
arch/mips/include/asm/syscall.h
arch/mips/include/uapi/asm/inst.h
arch/mips/include/uapi/asm/unistd.h
arch/mips/kernel/branch.c
arch/mips/kernel/proc.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/traps.c
arch/mips/lantiq/dts/easy50712.dts
arch/mips/lib/csum_partial.S
arch/mips/lib/delay.c
arch/mips/lib/strncpy_user.S
arch/mips/loongson/Kconfig
arch/mips/loongson/common/cs5536/cs5536_mfgpt.c
arch/mips/loongson/lemote-2f/clock.c
arch/mips/mm/page.c
arch/mips/mm/tlb-funcs.S
arch/mips/mm/tlbex.c
arch/mips/mti-malta/malta-memory.c
arch/mips/pci/pci-rc32434.c
arch/mips/ralink/dts/mt7620a_eval.dts
arch/mips/ralink/dts/rt2880_eval.dts
arch/mips/ralink/dts/rt3052_eval.dts
arch/mips/ralink/dts/rt3883_eval.dts
arch/parisc/Kconfig
arch/parisc/include/asm/processor.h
arch/parisc/include/uapi/asm/unistd.h
arch/parisc/kernel/sys_parisc.c
arch/parisc/kernel/syscall.S
arch/parisc/kernel/syscall_table.S
arch/parisc/kernel/traps.c
arch/parisc/mm/fault.c
arch/powerpc/Makefile
arch/powerpc/include/asm/ppc_asm.h
arch/powerpc/include/asm/sections.h
arch/powerpc/include/asm/systbl.h
arch/powerpc/include/asm/unistd.h
arch/powerpc/include/uapi/asm/unistd.h
arch/powerpc/kernel/kvm.c
arch/powerpc/kernel/machine_kexec_64.c
arch/powerpc/kernel/time.c
arch/powerpc/kvm/book3s.c
arch/powerpc/kvm/book3s_hv_rm_mmu.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_pr.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/platforms/powernv/eeh-ioda.c
arch/s390/crypto/aes_s390.c
arch/s390/crypto/des_s390.c
arch/s390/kvm/kvm-s390.c
arch/s390/net/bpf_jit_comp.c
arch/sparc/include/asm/pgtable_64.h
arch/sparc/include/asm/tsb.h
arch/sparc/kernel/head_64.S
arch/sparc/kernel/ktlb.S
arch/sparc/kernel/nmi.c
arch/sparc/kernel/smp_64.c
arch/sparc/kernel/sys32.S
arch/sparc/kernel/sysfs.c
arch/sparc/kernel/unaligned_64.c
arch/sparc/lib/NG2memcpy.S
arch/sparc/mm/fault_64.c
arch/sparc/mm/gup.c
arch/sparc/mm/init_64.c
arch/sparc/mm/tlb.c
arch/sparc/mm/tsb.c
arch/x86/Makefile
arch/x86/boot/Makefile
arch/x86/boot/compressed/misc.c
arch/x86/include/asm/hpet.h
arch/x86/include/asm/hugetlb.h
arch/x86/include/asm/page_64_types.h
arch/x86/include/asm/xen/hypercall.h
arch/x86/include/asm/xen/interface.h
arch/x86/include/uapi/asm/msr-index.h
arch/x86/kernel/acpi/sleep.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/cpu/mcheck/therm_throt.c
arch/x86/kernel/cpu/mcheck/threshold.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/rdrand.c
arch/x86/kernel/early-quirks.c
arch/x86/kernel/head32.c
arch/x86/kernel/head64.c
arch/x86/kernel/hpet.c
arch/x86/kernel/ldt.c
arch/x86/kernel/process_64.c
arch/x86/kernel/reboot.c
arch/x86/kernel/smp.c
arch/x86/kernel/traps.c
arch/x86/kernel/vsmp_64.c
arch/x86/kernel/vsyscall_gtod.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/lguest/boot.c
arch/x86/lib/msr.c
arch/x86/math-emu/errors.c
arch/x86/net/bpf_jit_comp.c
arch/x86/platform/efi/early_printk.c
arch/x86/platform/olpc/olpc-xo1-pm.c
arch/x86/power/hibernate_64.c
arch/x86/vdso/vdso32-setup.c
arch/x86/xen/enlighten.c
arch/x86/xen/irq.c
arch/x86/xen/mmu.c
arch/x86/xen/p2m.c
arch/x86/xen/setup.c
arch/x86/xen/suspend.c
arch/x86/xen/xen-ops.h
arch/xtensa/Kconfig
arch/xtensa/boot/dts/kc705.dts [new file with mode: 0644]
arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi [new file with mode: 0644]
arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
arch/xtensa/boot/dts/xtfpga.dtsi
arch/xtensa/include/asm/bootparam.h
arch/xtensa/include/asm/fixmap.h [new file with mode: 0644]
arch/xtensa/include/asm/highmem.h
arch/xtensa/include/asm/pgtable.h
arch/xtensa/include/asm/sysmem.h [new file with mode: 0644]
arch/xtensa/include/asm/tlbflush.h
arch/xtensa/kernel/setup.c
arch/xtensa/kernel/smp.c
arch/xtensa/kernel/xtensa_ksyms.c
arch/xtensa/mm/Makefile
arch/xtensa/mm/cache.c
arch/xtensa/mm/highmem.c [new file with mode: 0644]
arch/xtensa/mm/init.c
arch/xtensa/mm/mmu.c
arch/xtensa/mm/tlb.c
arch/xtensa/platforms/iss/Makefile
arch/xtensa/platforms/xt2000/setup.c
block/blk-cgroup.c
crypto/crypto_user.c
drivers/Makefile
drivers/acpi/Kconfig
drivers/acpi/Makefile
drivers/acpi/ac.c
drivers/acpi/acpi_platform.c
drivers/acpi/acpi_processor.c
drivers/acpi/acpica/acglobal.h
drivers/acpi/acpica/tbutils.c
drivers/acpi/battery.c
drivers/acpi/blacklist.c
drivers/acpi/cm_sbs.c [new file with mode: 0644]
drivers/acpi/thermal.c
drivers/acpi/video.c
drivers/ata/Kconfig
drivers/ata/ahci.c
drivers/ata/ahci.h
drivers/ata/ahci_imx.c
drivers/ata/libahci.c
drivers/ata/libata-core.c
drivers/block/ataflop.c
drivers/block/floppy.c
drivers/block/virtio_blk.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/bus/mvebu-mbus.c
drivers/char/agp/frontend.c
drivers/char/random.c
drivers/char/tpm/tpm_ppi.c
drivers/clk/bcm/clk-kona-setup.c
drivers/clk/bcm/clk-kona.c
drivers/clk/bcm/clk-kona.h
drivers/clk/clk-divider.c
drivers/clk/clk.c
drivers/clk/shmobile/clk-mstp.c
drivers/clk/socfpga/clk-pll.c
drivers/clk/socfpga/clk.c
drivers/clk/st/clkgen-pll.c
drivers/clk/tegra/clk-pll.c
drivers/clocksource/tcb_clksrc.c
drivers/clocksource/timer-marco.c
drivers/connector/cn_proc.c
drivers/cpufreq/cpufreq-cpu0.c
drivers/cpufreq/cpufreq_governor.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/loongson2_cpufreq.c
drivers/crypto/caam/error.c
drivers/dma/dmaengine.c
drivers/dma/dw/core.c
drivers/dma/mv_xor.c
drivers/dma/sa11x0-dma.c
drivers/firewire/core.h
drivers/firewire/ohci.c
drivers/firmware/iscsi_ibft.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/devres.c
drivers/gpio/gpio-adp5520.c
drivers/gpio/gpio-adp5588.c
drivers/gpio/gpio-bt8xx.c
drivers/gpio/gpio-davinci.c
drivers/gpio/gpio-dwapb.c
drivers/gpio/gpio-em.c
drivers/gpio/gpio-ep93xx.c
drivers/gpio/gpio-ge.c
drivers/gpio/gpio-generic.c
drivers/gpio/gpio-grgpio.c
drivers/gpio/gpio-ich.c
drivers/gpio/gpio-janz-ttl.c
drivers/gpio/gpio-kempld.c
drivers/gpio/gpio-lynxpoint.c
drivers/gpio/gpio-max730x.c
drivers/gpio/gpio-mcp23s08.c
drivers/gpio/gpio-moxart.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-palmas.c
drivers/gpio/gpio-pca953x.c
drivers/gpio/gpio-pcf857x.c
drivers/gpio/gpio-pch.c
drivers/gpio/gpio-pl061.c
drivers/gpio/gpio-rc5t583.c
drivers/gpio/gpio-rcar.c
drivers/gpio/gpio-rdc321x.c
drivers/gpio/gpio-sch.c
drivers/gpio/gpio-sch311x.c
drivers/gpio/gpio-spear-spics.c
drivers/gpio/gpio-sx150x.c
drivers/gpio/gpio-tc3589x.c
drivers/gpio/gpio-tegra.c
drivers/gpio/gpio-timberdale.c
drivers/gpio/gpio-tps6586x.c
drivers/gpio/gpio-tps65910.c
drivers/gpio/gpio-xilinx.c
drivers/gpio/gpio-zevio.c
drivers/gpio/gpiolib-acpi.c
drivers/gpio/gpiolib-of.c
drivers/gpio/gpiolib.c
drivers/gpio/gpiolib.h
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_evict.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_fbdev.c
drivers/gpu/drm/i915/intel_overlay.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_uncore.c
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c
drivers/gpu/drm/nouveau/core/subdev/bios/base.c
drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
drivers/gpu/drm/nouveau/nouveau_acpi.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/cik_sdma.c
drivers/gpu/drm/radeon/cikd.h
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_dma.c
drivers/gpu/drm/radeon/kv_dpm.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_dma.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_bios.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_family.h
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/radeon_ucode.h
drivers/gpu/drm/radeon/radeon_uvd.c
drivers/gpu/drm/radeon/radeon_vce.c
drivers/gpu/drm/radeon/radeon_vm.c
drivers/gpu/drm/radeon/rv770_dma.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/si_dma.c
drivers/gpu/drm/radeon/sid.h
drivers/gpu/drm/radeon/uvd_v1_0.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-multitouch.c
drivers/hid/hid-sensor-hub.c
drivers/hid/usbhid/hid-quirks.c
drivers/hwmon/Kconfig
drivers/hwmon/emc1403.c
drivers/hwmon/ntc_thermistor.c
drivers/i2c/busses/i2c-designware-core.c
drivers/i2c/busses/i2c-nomadik.c
drivers/i2c/busses/i2c-qup.c
drivers/i2c/busses/i2c-rcar.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/iio/adc/Kconfig
drivers/iio/adc/exynos_adc.c
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx4/mlx4_ib.h
drivers/infiniband/hw/mlx4/qp.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/infiniband/ulp/isert/ib_isert.h
drivers/input/keyboard/Kconfig
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/pxa27x_keypad.c
drivers/input/keyboard/tca8418_keypad.c
drivers/input/misc/bma150.c
drivers/input/mouse/Kconfig
drivers/input/mouse/elantech.c
drivers/input/mouse/elantech.h
drivers/input/mouse/synaptics.c
drivers/input/serio/ambakmi.c
drivers/input/touchscreen/Kconfig
drivers/iommu/amd_iommu.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/amd_iommu_v2.c
drivers/isdn/hisax/icc.c
drivers/md/dm-cache-target.c
drivers/md/dm-crypt.c
drivers/md/dm-mpath.c
drivers/md/dm-thin.c
drivers/md/md.c
drivers/md/raid10.c
drivers/media/i2c/ov7670.c
drivers/media/i2c/s5c73m3/s5c73m3-core.c
drivers/media/media-device.c
drivers/media/platform/davinci/vpbe_display.c
drivers/media/platform/davinci/vpfe_capture.c
drivers/media/platform/davinci/vpif_capture.c
drivers/media/platform/davinci/vpif_display.c
drivers/media/platform/exynos4-is/fimc-core.c
drivers/media/tuners/fc2580.c
drivers/media/tuners/fc2580_priv.h
drivers/media/usb/dvb-usb-v2/Makefile
drivers/media/usb/dvb-usb-v2/rtl28xxu.c
drivers/media/usb/gspca/sonixb.c
drivers/media/v4l2-core/v4l2-compat-ioctl32.c
drivers/memory/mvebu-devbus.c
drivers/mfd/rtsx_pcr.c
drivers/mmc/host/rtsx_pci_sdmmc.c
drivers/mtd/nand/davinci_nand.c
drivers/mtd/ubi/block.c
drivers/mtd/ubi/wl.c
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_options.c
drivers/net/bonding/bond_sysfs.c
drivers/net/bonding/bonding.h
drivers/net/can/c_can/c_can.c
drivers/net/can/c_can/c_can.h
drivers/net/can/c_can/c_can_pci.c
drivers/net/can/c_can/c_can_platform.c
drivers/net/can/dev.c
drivers/net/can/sja1000/peak_pci.c
drivers/net/can/sja1000/sja1000_isa.c
drivers/net/can/slcan.c
drivers/net/ethernet/Kconfig
drivers/net/ethernet/Makefile
drivers/net/ethernet/altera/Kconfig
drivers/net/ethernet/altera/Makefile
drivers/net/ethernet/altera/altera_msgdma.c
drivers/net/ethernet/altera/altera_msgdma.h
drivers/net/ethernet/altera/altera_msgdmahw.h
drivers/net/ethernet/altera/altera_sgdma.c
drivers/net/ethernet/altera/altera_sgdma.h
drivers/net/ethernet/altera/altera_sgdmahw.h
drivers/net/ethernet/altera/altera_tse.h
drivers/net/ethernet/altera/altera_tse_ethtool.c
drivers/net/ethernet/altera/altera_tse_main.c
drivers/net/ethernet/altera/altera_utils.c
drivers/net/ethernet/altera/altera_utils.h
drivers/net/ethernet/arc/emac.h
drivers/net/ethernet/arc/emac_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
drivers/net/ethernet/cadence/Kconfig
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/chelsio/Kconfig
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/ec_bhf.c [new file with mode: 0644]
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/freescale/gianfar_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/e1000e/phy.h
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_nvm.c
drivers/net/ethernet/intel/i40e/i40e_ptp.c
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/igb/e1000_i210.c
drivers/net/ethernet/intel/igb/e1000_mac.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igb/igb_ptp.c
drivers/net/ethernet/intel/ixgbe/ixgbe.h
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
drivers/net/ethernet/jme.c
drivers/net/ethernet/marvell/mvmdio.c
drivers/net/ethernet/mellanox/mlx4/cmd.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mlx4.h
drivers/net/ethernet/mellanox/mlx4/port.c
drivers/net/ethernet/mellanox/mlx4/qp.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c
drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c
drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h
drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c
drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c
drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h
drivers/net/ethernet/sfc/nic.c
drivers/net/ethernet/smsc/smc91x.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/sun/cassini.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/macvlan.c
drivers/net/macvtap.c
drivers/net/phy/mdio-gpio.c
drivers/net/phy/micrel.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/slip/slip.c
drivers/net/team/team.c
drivers/net/usb/cdc_mbim.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/qmi_wwan.c
drivers/net/virtio_net.c
drivers/net/vxlan.c
drivers/net/wireless/ath/ath9k/ahb.c
drivers/net/wireless/ath/ath9k/ani.c
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/debug_sta.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/pci.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/brcm80211/brcmfmac/chip.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/iwlwifi/mvm/coex.c
drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/rs.c
drivers/net/wireless/iwlwifi/mvm/scan.c
drivers/net/wireless/iwlwifi/mvm/utils.c
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/rt2x00/rt2x00mac.c
drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
drivers/net/wireless/rtlwifi/rtl8192se/trx.c
drivers/net/xen-netback/common.h
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/netback.c
drivers/of/base.c
drivers/pci/host/pci-mvebu.c
drivers/pci/hotplug/shpchp_ctrl.c
drivers/pci/pci.c
drivers/pinctrl/vt8500/pinctrl-wmt.c
drivers/pnp/pnpbios/bioscalls.c
drivers/ptp/Kconfig
drivers/rtc/rtc-hym8563.c
drivers/rtc/rtc-pcf8523.c
drivers/scsi/atari_scsi.c
drivers/scsi/scsi_netlink.c
drivers/scsi/scsi_transport_sas.c
drivers/sh/Makefile
drivers/sh/pm_runtime.c
drivers/spi/spi-pxa2xx-dma.c
drivers/spi/spi-qup.c
drivers/spi/spi.c
drivers/staging/iio/resolver/ad2s1200.c
drivers/staging/imx-drm/imx-drm-core.c
drivers/staging/imx-drm/imx-tve.c
drivers/staging/media/davinci_vpfe/vpfe_video.c
drivers/staging/media/sn9c102/sn9c102_devtable.h
drivers/staging/rtl8723au/os_dep/os_intfs.c
drivers/staging/rtl8723au/os_dep/usb_ops_linux.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_core.h
drivers/target/iscsi/iscsi_target_login.c
drivers/target/iscsi/iscsi_target_tpg.c
drivers/target/target_core_device.c
drivers/target/target_core_transport.c
drivers/target/tcm_fc/tfc_cmd.c
drivers/tty/hvc/hvc_console.c
drivers/tty/n_tty.c
drivers/tty/serial/8250/8250_core.c
drivers/tty/tty_buffer.c
drivers/usb/gadget/at91_udc.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ohci-hub.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/ohci.h
drivers/usb/phy/phy-fsm-usb.c
drivers/usb/serial/qcserial.c
drivers/usb/storage/shuttle_usbat.c
drivers/usb/storage/unusual_devs.h
drivers/video/fbdev/atafb.c
drivers/xen/events/events_fifo.c
drivers/xen/manage.c
drivers/xen/xen-acpi-processor.c
drivers/xen/xen-pciback/pci_stub.c
drivers/xen/xen-pciback/xenbus.c
fs/affs/super.c
fs/afs/cmservice.c
fs/afs/internal.h
fs/afs/rxrpc.c
fs/autofs4/root.c
fs/btrfs/ioctl.c
fs/btrfs/send.c
fs/ceph/caps.c
fs/ceph/dir.c
fs/ceph/inode.c
fs/ceph/ioctl.c
fs/ceph/locks.c
fs/ceph/super.h
fs/cifs/inode.c
fs/dcache.c
fs/exec.c
fs/fuse/control.c
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/hugetlbfs/inode.c
fs/kernfs/file.c
fs/locks.c
fs/namei.c
fs/nfsd/nfs4acl.c
fs/nfsd/nfs4state.c
fs/notify/fanotify/fanotify_user.c
fs/ocfs2/dlm/dlmmaster.c
fs/posix_acl.c
fs/splice.c
fs/sysfs/file.c
fs/sysfs/mount.c
fs/ubifs/super.c
fs/xfs/xfs_attr.c
fs/xfs/xfs_attr_leaf.c
fs/xfs/xfs_attr_list.c
fs/xfs/xfs_attr_remote.c
fs/xfs/xfs_da_btree.h
fs/xfs/xfs_export.c
fs/xfs/xfs_file.c
fs/xfs/xfs_iops.c
fs/xfs/xfs_log.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_qm.c
fs/xfs/xfs_sb.c
fs/xfs/xfs_super.c
include/asm-generic/resource.h
include/drm/drm_pciids.h
include/drm/i915_pciids.h
include/dt-bindings/clock/at91.h [moved from include/dt-bindings/clk/at91.h with 100% similarity]
include/linux/amba/bus.h
include/linux/cgroup.h
include/linux/dcache.h
include/linux/dmaengine.h
include/linux/gpio/consumer.h
include/linux/gpio/driver.h
include/linux/hugetlb.h
include/linux/if_macvlan.h
include/linux/if_vlan.h
include/linux/interrupt.h
include/linux/kernfs.h
include/linux/linkage.h
include/linux/mfd/rtsx_common.h
include/linux/mfd/rtsx_pci.h
include/linux/mfd/tc3589x.h
include/linux/mlx4/qp.h
include/linux/mm.h
include/linux/net.h
include/linux/netdevice.h
include/linux/netlink.h
include/linux/of.h
include/linux/of_gpio.h
include/linux/of_mdio.h
include/linux/omap-dma.h
include/linux/perf_event.h
include/linux/rtnetlink.h
include/linux/sched.h
include/linux/slub_def.h
include/linux/sock_diag.h
include/linux/tty.h
include/net/af_vsock.h
include/net/cfg80211.h
include/net/ip6_route.h
include/net/netns/ipv4.h
include/net/sock.h
include/trace/events/module.h
include/uapi/asm-generic/resource.h
include/uapi/asm-generic/unistd.h
include/uapi/linux/audit.h
include/uapi/linux/fuse.h
include/uapi/linux/nl80211.h
include/xen/interface/xen.h
include/xen/xen-ops.h
init/main.c
kernel/audit.c
kernel/cgroup.c
kernel/cgroup_freezer.c
kernel/context_tracking.c
kernel/cpu.c
kernel/events/core.c
kernel/futex.c
kernel/hrtimer.c
kernel/kexec.c
kernel/locking/lockdep.c
kernel/locking/rtmutex.c
kernel/power/snapshot.c
kernel/printk/printk.c
kernel/sched/core.c
kernel/sched/cpudeadline.c
kernel/sched/cpudeadline.h
kernel/sched/cpupri.c
kernel/sched/cpupri.h
kernel/sched/cputime.c
kernel/sched/deadline.c
kernel/sched/fair.c
kernel/softirq.c
kernel/tracepoint.c
kernel/workqueue.c
lib/dump_stack.c
mm/Kconfig
mm/compaction.c
mm/filemap.c
mm/hugetlb.c
mm/kmemleak.c
mm/madvise.c
mm/memcontrol.c
mm/memory-failure.c
mm/mremap.c
mm/page-writeback.c
mm/percpu.c
mm/slab.c
mm/slab.h
mm/slab_common.c
mm/slub.c
mm/truncate.c
mm/util.c
mm/vmscan.c
net/8021q/vlan.c
net/8021q/vlan_dev.c
net/batman-adv/bat_iv_ogm.c
net/batman-adv/distributed-arp-table.c
net/batman-adv/fragmentation.c
net/batman-adv/gateway_client.c
net/batman-adv/hard-interface.c
net/batman-adv/originator.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_event.c
net/bridge/br_netfilter.c
net/bridge/br_netlink.c
net/can/gw.c
net/ceph/messenger.c
net/ceph/osdmap.c
net/core/dev.c
net/core/filter.c
net/core/neighbour.c
net/core/net_namespace.c
net/core/rtnetlink.c
net/core/skbuff.c
net/core/sock.c
net/core/sock_diag.c
net/core/utils.c
net/dcb/dcbnl.c
net/decnet/dn_dev.c
net/decnet/dn_fib.c
net/decnet/netfilter/dn_rtmsg.c
net/dsa/dsa.c
net/ipv4/af_inet.c
net/ipv4/fib_semantics.c
net/ipv4/inet_connection_sock.c
net/ipv4/ip_forward.c
net/ipv4/ip_fragment.c
net/ipv4/ip_output.c
net/ipv4/ip_tunnel.c
net/ipv4/ip_vti.c
net/ipv4/netfilter/nf_defrag_ipv4.c
net/ipv4/ping.c
net/ipv4/route.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp_cubic.c
net/ipv4/tcp_output.c
net/ipv4/xfrm4_output.c
net/ipv4/xfrm4_protocol.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_offload.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/ip6mr.c
net/ipv6/ndisc.c
net/ipv6/netfilter.c
net/ipv6/netfilter/ip6t_rpfilter.c
net/ipv6/route.c
net/ipv6/tcpv6_offload.c
net/ipv6/xfrm6_output.c
net/ipv6/xfrm6_protocol.c
net/iucv/af_iucv.c
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
net/mac80211/offchannel.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/status.c
net/mac80211/trace.h
net/mac80211/util.c
net/mac80211/vht.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_tables_core.c
net/netfilter/nfnetlink.c
net/netlink/af_netlink.c
net/netlink/genetlink.c
net/packet/diag.c
net/phonet/pn_netlink.c
net/rxrpc/ar-key.c
net/sched/act_api.c
net/sched/cls_api.c
net/sched/cls_tcindex.c
net/sched/sch_api.c
net/sched/sch_hhf.c
net/sctp/protocol.c
net/sctp/sm_sideeffect.c
net/tipc/netlink.c
net/vmw_vsock/af_vsock.c
net/wireless/scan.c
net/wireless/sme.c
net/xfrm/xfrm_user.c
scripts/checksyscalls.sh
scripts/sortextable.c
security/apparmor/include/apparmor.h
security/apparmor/lib.c
security/device_cgroup.c
sound/core/pcm_dmaengine.c
sound/isa/sb/sb_mixer.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/tlv320aic31xx.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm8962.h
sound/soc/fsl/fsl_esai.c
sound/soc/fsl/imx-audmux.c
sound/soc/intel/sst-acpi.c
sound/soc/intel/sst-baytrail-dsp.c
sound/soc/intel/sst-baytrail-ipc.c
sound/soc/intel/sst-dsp-priv.h
sound/soc/intel/sst-dsp.c
sound/soc/intel/sst-dsp.h
sound/soc/intel/sst-firmware.c
sound/soc/intel/sst-haswell-dsp.c
sound/soc/intel/sst-haswell-ipc.c
sound/soc/intel/sst-haswell-ipc.h
sound/soc/intel/sst-haswell-pcm.c
sound/soc/sh/rcar/core.c
sound/soc/soc-dapm.c
sound/soc/soc-pcm.c
sound/usb/card.c
sound/usb/card.h
sound/usb/endpoint.c
sound/usb/pcm.c
sound/usb/usbaudio.h
tools/Makefile
tools/lib/lockdep/Makefile
tools/net/bpf_dbg.c

index a3c5a6685036103e7ec677272acdc4620d0302f6..ab8d76dfaa8096bbdf42bacf31336b856c07959b 100644 (file)
@@ -117,7 +117,7 @@ Description:
 
 What:          /sys/bus/pci/devices/.../vpd
 Date:          February 2008
-Contact:       Ben Hutchings <bhutchings@solarflare.com>
+Contact:       Ben Hutchings <bwh@kernel.org>
 Description:
                A file named vpd in a device directory will be a
                binary file containing the Vital Product Data for the
index 677a02553ec0cd772c1a86c73b7d314f48376190..ba60d93c18551af17db0e1bcbca7670662c025f9 100644 (file)
@@ -79,7 +79,7 @@
   <partintro>
     <para>
       This first part of the DRM Developer's Guide documents core DRM code,
-      helper libraries for writting drivers and generic userspace interfaces
+      helper libraries for writing drivers and generic userspace interfaces
       exposed by DRM drivers.
     </para>
   </partintro>
@@ -459,7 +459,7 @@ char *date;</synopsis>
       providing a solution to every graphics memory-related problems, GEM
       identified common code between drivers and created a support library to
       share it. GEM has simpler initialization and execution requirements than
-      TTM, but has no video RAM management capabitilies and is thus limited to
+      TTM, but has no video RAM management capabilities and is thus limited to
       UMA devices.
     </para>
     <sect2>
@@ -889,7 +889,7 @@ int (*prime_fd_to_handle)(struct drm_device *dev,
            vice versa. Drivers must use the kernel dma-buf buffer sharing framework
            to manage the PRIME file descriptors. Similar to the mode setting
            API PRIME is agnostic to the underlying buffer object manager, as
-           long as handles are 32bit unsinged integers.
+           long as handles are 32bit unsigned integers.
          </para>
          <para>
            While non-GEM drivers must implement the operations themselves, GEM
@@ -2356,7 +2356,7 @@ void intel_crt_init(struct drm_device *dev)
       first create properties and then create and associate individual instances
       of those properties to objects. A property can be instantiated multiple
       times and associated with different objects. Values are stored in property
-      instances, and all other property information are stored in the propery
+      instances, and all other property information are stored in the property
       and shared between all instances of the property.
     </para>
     <para>
@@ -2697,10 +2697,10 @@ int num_ioctls;</synopsis>
   <sect1>
     <title>Legacy Support Code</title>
     <para>
-      The section very brievely covers some of the old legacy support code which
+      The section very briefly covers some of the old legacy support code which
       is only used by old DRM drivers which have done a so-called shadow-attach
       to the underlying device instead of registering as a real driver. This
-      also includes some of the old generic buffer mangement and command
+      also includes some of the old generic buffer management and command
       submission code. Do not use any of this in new and modern drivers.
     </para>
 
index f9fd615427fbd4c0a718d66ed1b7de006ab796e6..1d27f0a1abd1e1872b0e05693ab35d6ecd64b0f2 100644 (file)
@@ -195,7 +195,7 @@ DVB_DOCUMENTED = \
 #
 
 install_media_images = \
-       $(Q)cp $(OBJIMGFILES) $(MEDIA_SRC_DIR)/v4l/*.svg $(MEDIA_OBJ_DIR)/media_api
+       $(Q)-cp $(OBJIMGFILES) $(MEDIA_SRC_DIR)/v4l/*.svg $(MEDIA_OBJ_DIR)/media_api
 
 $(MEDIA_OBJ_DIR)/%: $(MEDIA_SRC_DIR)/%.b64
        $(Q)base64 -d $< >$@
index 2a1519b87177244961df2ada70ea00a7dbfe4177..fd786ea13a1ffddf7477b191193cdc89e5eadc3e 100644 (file)
@@ -296,7 +296,7 @@ specifies the path to the controller. In order to use these GPIOs in Linux
 we need to translate them to the corresponding Linux GPIO descriptors.
 
 There is a standard GPIO API for that and is documented in
-Documentation/gpio.txt.
+Documentation/gpio/.
 
 In the above example we can get the corresponding two GPIO descriptors with
 a code like this:
index fa0151a712f9c5a0d9fe43db6e0746ff4046a5e0..5c9a567b3fac0a6907343608a550583268cd5450 100644 (file)
@@ -25,9 +25,11 @@ using data transfer rates in the order of 10MB/s or more.
 With most FireWire controllers, memory access is limited to the low 4 GB
 of physical address space.  This can be a problem on IA64 machines where
 memory is located mostly above that limit, but it is rarely a problem on
-more common hardware such as x86, x86-64 and PowerPC.  However, at least
-Agere/LSI FW643e and FW643e2 controllers are known to support access to
-physical addresses above 4 GB.
+more common hardware such as x86, x86-64 and PowerPC.
+
+At least LSI FW643e and FW643e2 controllers are known to support access to
+physical addresses above 4 GB, but this feature is currently not enabled by
+Linux.
 
 Together with a early initialization of the OHCI-1394 controller for debugging,
 this facility proved most useful for examining long debugs logs in the printk
@@ -101,8 +103,9 @@ Step-by-step instructions for using firescope with early OHCI initialization:
    compliant, they are based on TI PCILynx chips and require drivers for Win-
    dows operating systems.
 
-   The mentioned kernel log message contains ">4 GB phys DMA" in case of
-   OHCI-1394 controllers which support accesses above this limit.
+   The mentioned kernel log message contains the string "physUB" if the
+   controller implements a writable Physical Upper Bound register.  This is
+   required for physical DMA above 4 GB (but not utilized by Linux yet).
 
 2) Establish a working FireWire cable connection:
 
index 05a27e9442bd4e5c4d3e618a6a0594e55466b192..2f5173500bd953b32e55134012af50ac93e46ad8 100644 (file)
@@ -309,7 +309,10 @@ ii) Status
     error_if_no_space|queue_if_no_space
        If the pool runs out of data or metadata space, the pool will
        either queue or error the IO destined to the data device.  The
-       default is to queue the IO until more space is added.
+       default is to queue the IO until more space is added or the
+       'no_space_timeout' expires.  The 'no_space_timeout' dm-thin-pool
+       module parameter can be used to change this timeout -- it
+       defaults to 60 seconds but may be disabled using a value of 0.
 
 iii) Messages
 
index cd5e23912888cf4350750fe0adc908fb895e3d08..6794cdc96d8fdf44513a4ad2310fe67a2a93712d 100644 (file)
@@ -62,7 +62,7 @@ Required properties for PMC node:
 - interrupt-controller : tell that the PMC is an interrupt controller.
 - #interrupt-cells : must be set to 1. The first cell encodes the interrupt id,
        and reflect the bit position in the PMC_ER/DR/SR registers.
-       You can use the dt macros defined in dt-bindings/clk/at91.h.
+       You can use the dt macros defined in dt-bindings/clock/at91.h.
        0 (AT91_PMC_MOSCS) -> main oscillator ready
        1 (AT91_PMC_LOCKA) -> PLL A ready
        2 (AT91_PMC_LOCKB) -> PLL B ready
index 5992dceec7af7d1e9d1ac8f329b831d48e409d87..02a25d99ca61bfb33a46a2ce8e547b7f22d3c73a 100644 (file)
@@ -43,7 +43,7 @@ Example
                clock-output-names =
                        "tpu0", "mmcif1", "sdhi3", "sdhi2",
                         "sdhi1", "sdhi0", "mmcif0";
-               renesas,clock-indices = <
+               clock-indices = <
                        R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SDHI3
                        R8A7790_CLK_SDHI2 R8A7790_CLK_SDHI1 R8A7790_CLK_SDHI0
                        R8A7790_CLK_MMCIF0
index 9fbbdb783a72d50600755a074cbc11cfba97f713..68ff2137bae7261e84409a472fbf432989fca0d6 100644 (file)
@@ -29,6 +29,6 @@ edma: edma@49000000 {
        dma-channels = <64>;
        ti,edma-regions = <4>;
        ti,edma-slots = <256>;
-       ti,edma-xbar-event-map = <1 12
-                                 2 13>;
+       ti,edma-xbar-event-map = /bits/ 16 <1 12
+                                           2 13>;
 };
index f61cef74a2124ccdbd222802a4f340e88b1f6ef3..941a26aa43228647dc021527c894a6ceb0d69d88 100644 (file)
@@ -21,6 +21,12 @@ Required Properties:
     GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported.
   - gpio-ranges: Range of pins managed by the GPIO controller.
 
+Optional properties:
+
+  - clocks: Must contain a reference to the functional clock.  The property is
+    mandatory if the hardware implements a controllable functional clock for
+    the GPIO instance.
+
 Please refer to gpio.txt in this directory for details of gpio-ranges property
 and the common GPIO bindings used by client devices.
 
index 7fbb027218a126002312a829c6cd273ac715b030..a1d71eb43b209485ac7bec4832119f25fe68a49e 100644 (file)
@@ -4,11 +4,15 @@ Required properties:
 - compatible: Should be "snps,arc-emac"
 - reg: Address and length of the register set for the device
 - interrupts: Should contain the EMAC interrupts
-- clock-frequency: CPU frequency. It is needed to calculate and set polling
-period of EMAC.
 - max-speed: see ethernet.txt file in the same directory.
 - phy: see ethernet.txt file in the same directory.
 
+Clock handling:
+The clock frequency is needed to calculate and set polling period of EMAC.
+It must be provided by one of:
+- clock-frequency: CPU frequency.
+- clocks: reference to the clock supplying the EMAC.
+
 Child nodes of the driver are the individual PHY devices connected to the
 MDIO bus. They must have a "reg" property given the PHY address on the MDIO bus.
 
@@ -19,7 +23,11 @@ Examples:
                reg = <0xc0fc2000 0x3c>;
                interrupts = <6>;
                mac-address = [ 00 11 22 33 44 55 ];
+
                clock-frequency = <80000000>;
+               /* or */
+               clocks = <&emac_clock>;
+
                max-speed = <100>;
                phy = <&phy0>;
 
index c79bab025369af4bb6320ba0e90f7fb386942cc1..8dbcf8295c6c9ceaa4eb7518694acf3b09095dc1 100644 (file)
@@ -14,7 +14,7 @@ node.
 Example:
 
 aliases {
-       mdio-gpio0 = <&mdio0>;
+       mdio-gpio0 = &mdio0;
 };
 
 mdio0: mdio {
index 4f7897e99cba8a8fc7b5a33343825cfb94ce2d68..10b8c5d2c79701e9d33e1f8e31ba1339e056973f 100644 (file)
@@ -308,3 +308,10 @@ SLAVE DMA ENGINE
 
 SPI
   devm_spi_register_master()
+
+GPIO
+  devm_gpiod_get()
+  devm_gpiod_get_index()
+  devm_gpiod_get_optional()
+  devm_gpiod_get_index_optional()
+  devm_gpiod_put()
index e9f5daccbd02e2d8e97b489faf372dbb307529d8..4e30ebaa9e5b2652950b2383817e852d2e2239e0 100644 (file)
@@ -201,20 +201,15 @@ To beat some sense out of the internal editor, do this:
 
 - Edit your Thunderbird config settings so that it won't use format=flowed.
   Go to "edit->preferences->advanced->config editor" to bring up the
-  thunderbird's registry editor, and set "mailnews.send_plaintext_flowed" to
-  "false".
+  thunderbird's registry editor.
 
-- Disable HTML Format: Set "mail.identity.id1.compose_html" to "false".
+- Set "mailnews.send_plaintext_flowed" to "false"
 
-- Enable "preformat" mode: Set "editor.quotesPreformatted" to "true".
+- Set "mailnews.wraplength" from "72" to "0"
 
-- Enable UTF8: Set "prefs.converted-to-utf8" to "true".
+- "View" > "Message Body As" > "Plain Text"
 
-- Install the "toggle wordwrap" extension.  Download the file from:
-    https://addons.mozilla.org/thunderbird/addon/2351/
-  Then go to "tools->add ons", select "install" at the bottom of the screen,
-  and browse to where you saved the .xul file.  This adds an "Enable
-  Wordwrap" entry under the Options menu of the message composer.
+- "View" > "Character Encoding" > "Unicode (UTF-8)"
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 TkRat (GUI)
index 8b9cd8eb3f917e63074ba0ffae0e83b767a87176..264bcde0c51c55629066e9809af3bab99fe05c8c 100644 (file)
@@ -1245,8 +1245,9 @@ second).  The meanings of the columns are as follows, from left to right:
 
 The "intr" line gives counts of interrupts  serviced since boot time, for each
 of the  possible system interrupts.   The first  column  is the  total of  all
-interrupts serviced; each  subsequent column is the  total for that particular
-interrupt.
+interrupts serviced  including  unnumbered  architecture specific  interrupts;
+each  subsequent column is the  total for that particular numbered interrupt.
+Unnumbered interrupts are not shown, only summed into the total.
 
 The "ctxt" line gives the total number of context switches across all CPUs.
 
index f73cc7b5dc853df94b05a035b9531bc215648471..fa9a0a8b37348273df54a56c6c0022da94078078 100644 (file)
@@ -73,6 +73,65 @@ The IRQ portions of the GPIO block are implemented using an irqchip, using
 the header <linux/irq.h>. So basically such a driver is utilizing two sub-
 systems simultaneously: gpio and irq.
 
+GPIO irqchips usually fall in one of two categories:
+
+* CHAINED GPIO irqchips: these are usually the type that is embedded on
+  an SoC. This means that there is a fast IRQ handler for the GPIOs that
+  gets called in a chain from the parent IRQ handler, most typically the
+  system interrupt controller. This means the GPIO irqchip is registered
+  using irq_set_chained_handler() or the corresponding
+  gpiochip_set_chained_irqchip() helper function, and the GPIO irqchip
+  handler will be called immediately from the parent irqchip, while
+  holding the IRQs disabled. The GPIO irqchip will then end up calling
+  something like this sequence in its interrupt handler:
+
+  static irqreturn_t tc3589x_gpio_irq(int irq, void *data)
+      chained_irq_enter(...);
+      generic_handle_irq(...);
+      chained_irq_exit(...);
+
+  Chained GPIO irqchips typically can NOT set the .can_sleep flag on
+  struct gpio_chip, as everything happens directly in the callbacks.
+
+* NESTED THREADED GPIO irqchips: these are off-chip GPIO expanders and any
+  other GPIO irqchip residing on the other side of a sleeping bus. Of course
+  such drivers that need slow bus traffic to read out IRQ status and similar,
+  traffic which may in turn incur other IRQs to happen, cannot be handled
+  in a quick IRQ handler with IRQs disabled. Instead they need to spawn a
+  thread and then mask the parent IRQ line until the interrupt is handled
+  by the driver. The hallmark of this driver is to call something like
+  this in its interrupt handler:
+
+  static irqreturn_t tc3589x_gpio_irq(int irq, void *data)
+      ...
+      handle_nested_irq(irq);
+
+  The hallmark of threaded GPIO irqchips is that they set the .can_sleep
+  flag on struct gpio_chip to true, indicating that this chip may sleep
+  when accessing the GPIOs.
+
+To help out in handling the set-up and management of GPIO irqchips and the
+associated irqdomain and resource allocation callbacks, the gpiolib has
+some helpers that can be enabled by selecting the GPIOLIB_IRQCHIP Kconfig
+symbol:
+
+* gpiochip_irqchip_add(): adds an irqchip to a gpiochip. It will pass
+  the struct gpio_chip* for the chip to all IRQ callbacks, so the callbacks
+  need to embed the gpio_chip in its state container and obtain a pointer
+  to the container using container_of().
+  (See Documentation/driver-model/design-patterns.txt)
+
+* gpiochip_set_chained_irqchip(): sets up a chained irq handler for a
+  gpio_chip from a parent IRQ and passes the struct gpio_chip* as handler
+  data. (Notice handler data, since the irqchip data is likely used by the
+  parent irqchip!) This is for the chained type of chip.
+
+To use the helpers please keep the following in mind:
+
+- Make sure to assign all relevant members of the struct gpio_chip so that
+  the irqchip can initialize. E.g. .dev and .can_sleep shall be set up
+  properly.
+
 It is legal for any IRQ consumer to request an IRQ from any irqchip no matter
 if that is a combined GPIO+IRQ driver. The basic premise is that gpio_chip and
 irq_chip are orthogonal, and offering their services independent of each
index 79f8257dd790703f8a9285e7b498f585df87e97b..2cc95ad466047b055d45f748619cf2d7231d5e93 100644 (file)
@@ -327,6 +327,13 @@ temp[1-*]_max_hyst
                from the max value.
                RW
 
+temp[1-*]_min_hyst
+               Temperature hysteresis value for min limit.
+               Unit: millidegree Celsius
+               Must be reported as an absolute temperature, NOT a delta
+               from the min value.
+               RW
+
 temp[1-*]_input Temperature input value.
                Unit: millidegree Celsius
                RO
@@ -362,6 +369,13 @@ temp[1-*]_lcrit    Temperature critical min value, typically lower than
                Unit: millidegree Celsius
                RW
 
+temp[1-*]_lcrit_hyst
+               Temperature hysteresis value for critical min limit.
+               Unit: millidegree Celsius
+               Must be reported as an absolute temperature, NOT a delta
+               from the critical min value.
+               RW
+
 temp[1-*]_offset
                Temperature offset which is added to the temperature reading
                by the chip.
index 5602eb71ad5d7318e50952846d4f82edd3dcc239..e1ae127ed099d4934e1d7fb95f1a8ba819c1da9b 100644 (file)
@@ -504,9 +504,12 @@ byte 5:
 * reg_10
 
    bit   7   6   5   4   3   2   1   0
-         0   0   0   0   0   0   0   A
+         0   0   0   0   R   F   T   A
 
          A: 1 = enable absolute tracking
+         T: 1 = enable two finger mode auto correct
+         F: 1 = disable ABS Position Filter
+         R: 1 = enable real hardware resolution
 
 6.2 Native absolute mode 6 byte packet format
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
index e6a72328154783fc6e983904658eb8eb8c0c4ee8..418020584ccc171b8ff079e496e73383f0f55c29 100644 (file)
@@ -188,6 +188,9 @@ shift
 #define CP_METHODREF 10
 #define CP_INTERFACEMETHODREF 11
 #define CP_NAMEANDTYPE 12
+#define CP_METHODHANDLE 15
+#define CP_METHODTYPE 16
+#define CP_INVOKEDYNAMIC 18
 
 /* Define some commonly used error messages */
 
@@ -242,14 +245,19 @@ void skip_constant(FILE *classfile, u_int16_t *cur)
                break;
        case CP_CLASS:
        case CP_STRING:
+       case CP_METHODTYPE:
                seekerr = fseek(classfile, 2, SEEK_CUR);
                break;
+       case CP_METHODHANDLE:
+               seekerr = fseek(classfile, 3, SEEK_CUR);
+               break;
        case CP_INTEGER:
        case CP_FLOAT:
        case CP_FIELDREF:
        case CP_METHODREF:
        case CP_INTERFACEMETHODREF:
        case CP_NAMEANDTYPE:
+       case CP_INVOKEDYNAMIC:
                seekerr = fseek(classfile, 4, SEEK_CUR);
                break;
        case CP_LONG:
index 43842177b771d72e67e90361f79b28966435787f..7da289ee058944da04243d818e3727a72c4747a6 100644 (file)
@@ -892,7 +892,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        (mmio) or 32-bit (mmio32).
                        The options are the same as for ttyS, above.
 
-       earlyprintk=    [X86,SH,BLACKFIN,ARM]
+       earlyprintk=    [X86,SH,BLACKFIN,ARM,M68k]
                        earlyprintk=vga
                        earlyprintk=efi
                        earlyprintk=xen
@@ -2218,10 +2218,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        noreplace-smp   [X86-32,SMP] Don't replace SMP instructions
                        with UP alternatives
 
-       nordrand        [X86] Disable the direct use of the RDRAND
-                       instruction even if it is supported by the
-                       processor.  RDRAND is still available to user
-                       space applications.
+       nordrand        [X86] Disable kernel use of the RDRAND and
+                       RDSEED instructions even if they are supported
+                       by the processor.  RDRAND and RDSEED are still
+                       available to user space applications.
 
        noresume        [SWSUSP] Disables resume and restores original swap
                        space.
index 81f940f4e88480d48c35fd7707d679d646ef0af8..e3ba753cb714949c4e26f898da31b6d0e6b03737 100644 (file)
@@ -277,7 +277,7 @@ Possible BPF extensions are shown in the following table:
   mark                                  skb->mark
   queue                                 skb->queue_mapping
   hatype                                skb->dev->type
-  rxhash                                skb->rxhash
+  rxhash                                skb->hash
   cpu                                   raw_smp_processor_id()
   vlan_tci                              vlan_tx_tag_get(skb)
   vlan_pr                               vlan_tx_tag_present(skb)
index 6fea79efb4cbfd31cc1d0155aef320b94b89da9e..38112d512f47db9ec9a70edae7c7df83b7d13119 100644 (file)
@@ -578,7 +578,7 @@ processes. This also works in combination with mmap(2) on packet sockets.
 
 Currently implemented fanout policies are:
 
-  - PACKET_FANOUT_HASH: schedule to socket by skb's rxhash
+  - PACKET_FANOUT_HASH: schedule to socket by skb's packet hash
   - PACKET_FANOUT_LB: schedule to socket by round-robin
   - PACKET_FANOUT_CPU: schedule to socket by CPU packet arrives on
   - PACKET_FANOUT_RND: schedule to socket by random selection
index ca6977f5b2ed066f49823c0d7c0129a9a16b0820..99ca40e8e810888d30bbb9726eb2de2e537c3e79 100644 (file)
@@ -429,7 +429,7 @@ RPS and RFS were introduced in kernel 2.6.35. XPS was incorporated into
 (therbert@google.com)
 
 Accelerated RFS was introduced in 2.6.35. Original patches were
-submitted by Ben Hutchings (bhutchings@solarflare.com)
+submitted by Ben Hutchings (bwh@kernel.org)
 
 Authors:
 Tom Herbert (therbert@google.com)
index a9380ba54c8e984a997edb65fae8be9fef02f761..b4f53653c106d40d648930776e3258278c476932 100644 (file)
@@ -2126,7 +2126,7 @@ into the hash PTE second double word).
 4.75 KVM_IRQFD
 
 Capability: KVM_CAP_IRQFD
-Architectures: x86
+Architectures: x86 s390
 Type: vm ioctl
 Parameters: struct kvm_irqfd (in)
 Returns: 0 on success, -1 on error
index 106626442124d6e849d106f9bb1bdf972be443b0..c496c311ffba5dd9ff89b1d7b861f324675c188a 100644 (file)
@@ -537,7 +537,7 @@ L:  linux-alpha@vger.kernel.org
 F:     arch/alpha/
 
 ALTERA TRIPLE SPEED ETHERNET DRIVER
-M:     Vince Bridgers <vbridgers2013@gmail.com
+M:     Vince Bridgers <vbridgers2013@gmail.com>
 L:     netdev@vger.kernel.org
 L:     nios2-dev@lists.rocketboards.org (moderated for non-subscribers)
 S:     Maintained
@@ -1893,14 +1893,15 @@ L:      netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/broadcom/bnx2x/
 
-BROADCOM BCM281XX/BCM11XXX ARM ARCHITECTURE
+BROADCOM BCM281XX/BCM11XXX/BCM216XX ARM ARCHITECTURE
 M:     Christian Daudt <bcm@fixthebug.org>
 M:     Matt Porter <mporter@linaro.org>
 L:     bcm-kernel-feedback-list@broadcom.com
-T:     git git://git.github.com/broadcom/bcm11351
+T:     git git://github.com/broadcom/mach-bcm
 S:     Maintained
 F:     arch/arm/mach-bcm/
 F:     arch/arm/boot/dts/bcm113*
+F:     arch/arm/boot/dts/bcm216*
 F:     arch/arm/boot/dts/bcm281*
 F:     arch/arm/configs/bcm_defconfig
 F:     drivers/mmc/host/sdhci_bcm_kona.c
@@ -2245,12 +2246,6 @@ L:       linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/host/ohci-ep93xx.c
 
-CIRRUS LOGIC CS4270 SOUND DRIVER
-M:     Timur Tabi <timur@tabi.org>
-L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
-S:     Odd Fixes
-F:     sound/soc/codecs/cs4270*
-
 CIRRUS LOGIC AUDIO CODEC DRIVERS
 M:     Brian Austin <brian.austin@cirrus.com>
 M:     Paul Handrigan <Paul.Handrigan@cirrus.com>
@@ -4818,6 +4813,14 @@ L:       linux-kernel@vger.kernel.org
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
 F:     kernel/irq/
+
+IRQCHIP DRIVERS
+M:     Thomas Gleixner <tglx@linutronix.de>
+M:     Jason Cooper <jason@lakedaemon.net>
+L:     linux-kernel@vger.kernel.org
+S:     Maintained
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
+T:     git git://git.infradead.org/users/jcooper/linux.git irqchip/core
 F:     drivers/irqchip/
 
 IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
@@ -5490,15 +5493,15 @@ F:      Documentation/hwmon/ltc4261
 F:     drivers/hwmon/ltc4261.c
 
 LTP (Linux Test Project)
-M:     Shubham Goyal <shubham@linux.vnet.ibm.com>
 M:     Mike Frysinger <vapier@gentoo.org>
 M:     Cyril Hrubis <chrubis@suse.cz>
-M:     Caspar Zhang <caspar@casparzhang.com>
 M:     Wanlong Gao <gaowanlong@cn.fujitsu.com>
+M:     Jan Stancek <jstancek@redhat.com>
+M:     Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com>
+M:     Alexey Kodanev <alexey.kodanev@oracle.com>
 L:     ltp-list@lists.sourceforge.net (subscribers-only)
-W:     http://ltp.sourceforge.net/
+W:     http://linux-test-project.github.io/
 T:     git git://github.com/linux-test-project/ltp.git
-T:     git git://ltp.git.sourceforge.net/gitroot/ltp/ltp-dev
 S:     Maintained
 
 M32R ARCHITECTURE
@@ -6415,6 +6418,7 @@ F:        drivers/usb/*/*omap*
 F:     arch/arm/*omap*/usb*
 
 OMAP GPIO DRIVER
+M:     Javier Martinez Canillas <javier@dowhile0.org>
 M:     Santosh Shilimkar <santosh.shilimkar@ti.com>
 M:     Kevin Hilman <khilman@deeprootsystems.com>
 L:     linux-omap@vger.kernel.org
@@ -6511,10 +6515,10 @@ T:      git git://openrisc.net/~jonas/linux
 F:     arch/openrisc/
 
 OPENVSWITCH
-M:     Jesse Gross <jesse@nicira.com>
+M:     Pravin Shelar <pshelar@nicira.com>
 L:     dev@openvswitch.org
 W:     http://openvswitch.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jesse/openvswitch.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/pshelar/openvswitch.git
 S:     Maintained
 F:     net/openvswitch/
 
@@ -7288,7 +7292,6 @@ F:        drivers/video/aty/aty128fb.c
 RALINK RT2X00 WIRELESS LAN DRIVER
 P:     rt2x00 project
 M:     Ivo van Doorn <IvDoorn@gmail.com>
-M:     Gertjan van Wingerde <gwingerde@gmail.com>
 M:     Helmut Schaa <helmut.schaa@googlemail.com>
 L:     linux-wireless@vger.kernel.org
 L:     users@rt2x00.serialmonkey.com (moderated for non-subscribers)
@@ -7304,7 +7307,7 @@ F:        Documentation/blockdev/ramdisk.txt
 F:     drivers/block/brd.c
 
 RANDOM NUMBER DRIVER
-M:     Theodore Ts'o" <tytso@mit.edu>
+M:     "Theodore Ts'o" <tytso@mit.edu>
 S:     Maintained
 F:     drivers/char/random.c
 
@@ -7403,6 +7406,14 @@ F:       drivers/rpmsg/
 F:     Documentation/rpmsg.txt
 F:     include/linux/rpmsg.h
 
+RESET CONTROLLER FRAMEWORK
+M:     Philipp Zabel <p.zabel@pengutronix.de>
+S:     Maintained
+F:     drivers/reset/
+F:     Documentation/devicetree/bindings/reset/
+F:     include/linux/reset.h
+F:     include/linux/reset-controller.h
+
 RFKILL
 M:     Johannes Berg <johannes@sipsolutions.net>
 L:     linux-wireless@vger.kernel.org
@@ -7685,7 +7696,6 @@ F:        drivers/clk/samsung/
 SAMSUNG SXGBE DRIVERS
 M:     Byungho An <bh74.an@samsung.com>
 M:     Girish K S <ks.giri@samsung.com>
-M:     Siva Reddy Kallam <siva.kallam@samsung.com>
 M:     Vipul Pandya <vipul.pandya@samsung.com>
 S:     Supported
 L:     netdev@vger.kernel.org
@@ -9109,6 +9119,9 @@ F:        arch/um/os-Linux/drivers/
 
 TURBOCHANNEL SUBSYSTEM
 M:     "Maciej W. Rozycki" <macro@linux-mips.org>
+M:     Ralf Baechle <ralf@linux-mips.org>
+L:     linux-mips@linux-mips.org
+Q:     http://patchwork.linux-mips.org/project/linux-mips/list/
 S:     Maintained
 F:     drivers/tc/
 F:     include/linux/tc.h
@@ -9962,7 +9975,7 @@ F:        drivers/net/hamradio/*scc.c
 F:     drivers/net/hamradio/z8530.h
 
 ZBUD COMPRESSED PAGE ALLOCATOR
-M:     Seth Jennings <sjenning@linux.vnet.ibm.com>
+M:     Seth Jennings <sjennings@variantweb.net>
 L:     linux-mm@kvack.org
 S:     Maintained
 F:     mm/zbud.c
@@ -10007,7 +10020,7 @@ F:      mm/zsmalloc.c
 F:     include/linux/zsmalloc.h
 
 ZSWAP COMPRESSED SWAP CACHING
-M:     Seth Jennings <sjenning@linux.vnet.ibm.com>
+M:     Seth Jennings <sjennings@variantweb.net>
 L:     linux-mm@kvack.org
 S:     Maintained
 F:     mm/zswap.c
index 28a7259e0f3b53ed0ee9242fcea45abc71c004f1..cdaa5b6a1c4d6e43e4c0c784831e1e3cb0d9fae5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 15
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc8
 NAME = Shuffling Zombie Juror
 
 # *DOCUMENTATION*
index cb6811e5ae5a9a148321d4e667dc34cde9bc9846..7ad75b4e066358f5229d93d0d017c754a711ca32 100644 (file)
                        compatible = "ti,edma3";
                        ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
                        reg =   <0x49000000 0x10000>,
-                               <0x44e10f90 0x10>;
+                               <0x44e10f90 0x40>;
                        interrupts = <12 13 14>;
                        #dma-cells = <1>;
                        dma-channels = <64>;
index 788391f916844130d8d6cdb2722479163863a707..5a452fdd7c5d9711cec9f6d0196f90b0726fefc3 100644 (file)
        };
 };
 
+&iva {
+       status = "disabled";
+};
+
+&mailbox {
+       status = "disabled";
+};
+
+&mmu_isp {
+       status = "disabled";
+};
+
+&smartreflex_mpu_iva {
+       status = "disabled";
+};
+
 /include/ "am35xx-clocks.dtsi"
 /include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi"
index df8798e8bd255bbf789da0b44f5229b9f3dc80dd..a055f7f0f14ae5a3e080489c9c424bd37be0e1c0 100644 (file)
        status = "okay";
 };
 
+&gpio5 {
+       status = "okay";
+       ti,no-reset-on-init;
+};
+
 &mmc1 {
        status = "okay";
        vmmc-supply = <&vmmcsd_fixed>;
index 82f238a9063ffe47d10dbe083f136e1876f8efd2..3383c4b668035737e1812777fed34a03f5f9ef7c 100644 (file)
@@ -67,6 +67,7 @@
                        i2c@11000 {
                                pinctrl-0 = <&i2c0_pins>;
                                pinctrl-names = "default";
+                               clock-frequency = <100000>;
                                status = "okay";
                                audio_codec: audio-codec@4a {
                                        compatible = "cirrus,cs42l51";
index 9378d3136b41d7b37f11abdf01186c019758f7f1..0451124e8ebf49af45b34072ae69a02a6fa133a9 100644 (file)
                                };
                        };
 
+                       sata@a0000 {
+                               status = "okay";
+                               nr-ports = <2>;
+                       };
+
                        nand: nand@d0000 {
                                pinctrl-0 = <&nand_pins>;
                                pinctrl-names = "default";
index 068031f0f263ef081f590eae7ac3da0df629ab2d..6d0f03c98ee919adb2609ad16ee7763fee3c65bc 100644 (file)
@@ -99,7 +99,7 @@
                        pcie@3,0 {
                                device_type = "pci";
                                assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
-                               reg = <0x1000 0 0 0 0>;
+                               reg = <0x1800 0 0 0 0>;
                                #address-cells = <3>;
                                #size-cells = <2>;
                                #interrupt-cells = <1>;
index e2919f02e1d47687c77477b1a9bd389a32a4134e..da801964a25783a5f11d1aa22afe1cd1e2cc9da9 100644 (file)
                        pcie@3,0 {
                                device_type = "pci";
                                assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
-                               reg = <0x1000 0 0 0 0>;
+                               reg = <0x1800 0 0 0 0>;
                                #address-cells = <3>;
                                #size-cells = <2>;
                                #interrupt-cells = <1>;
                        pcie@4,0 {
                                device_type = "pci";
                                assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
-                               reg = <0x1000 0 0 0 0>;
+                               reg = <0x2000 0 0 0 0>;
                                #address-cells = <3>;
                                #size-cells = <2>;
                                #interrupt-cells = <1>;
index 448373c4b0e534c1d2ce08592981f5d38bad39a8..90f0bf6f92715c7335072bda5b508e7800fa89a4 100644 (file)
@@ -49,7 +49,7 @@
                        /* Device Bus parameters are required */
 
                        /* Read parameters */
-                       devbus,bus-width    = <8>;
+                       devbus,bus-width    = <16>;
                        devbus,turn-off-ps  = <60000>;
                        devbus,badr-skew-ps = <0>;
                        devbus,acc-first-ps = <124000>;
index 61bda687f782f65485f958adb8d8ec2822ebde35..0c756421ae6aa5f504b72898c16875bdaab5f8d3 100644 (file)
@@ -59,7 +59,7 @@
                        /* Device Bus parameters are required */
 
                        /* Read parameters */
-                       devbus,bus-width    = <8>;
+                       devbus,bus-width    = <16>;
                        devbus,turn-off-ps  = <60000>;
                        devbus,badr-skew-ps = <0>;
                        devbus,acc-first-ps = <124000>;
                        ethernet@70000 {
                                status = "okay";
                                phy = <&phy0>;
-                               phy-mode = "rgmii-id";
+                               phy-mode = "qsgmii";
                        };
                        ethernet@74000 {
                                status = "okay";
                                phy = <&phy1>;
-                               phy-mode = "rgmii-id";
+                               phy-mode = "qsgmii";
                        };
                        ethernet@30000 {
                                status = "okay";
                                phy = <&phy2>;
-                               phy-mode = "rgmii-id";
+                               phy-mode = "qsgmii";
                        };
                        ethernet@34000 {
                                status = "okay";
                                phy = <&phy3>;
-                               phy-mode = "rgmii-id";
+                               phy-mode = "qsgmii";
                        };
 
                        /* Front-side USB slot */
index 985948ce67b3271a65c9b4a413a99e7d255b12e7..5d42feb3104983a2ee9b21be33b59cc2e66a1bcd 100644 (file)
@@ -39,7 +39,7 @@
                        /* Device Bus parameters are required */
 
                        /* Read parameters */
-                       devbus,bus-width    = <8>;
+                       devbus,bus-width    = <16>;
                        devbus,turn-off-ps  = <60000>;
                        devbus,badr-skew-ps = <0>;
                        devbus,acc-first-ps = <124000>;
index ce1375595e5f27117c37881bcafa5fc5805b1455..4537259ce5299baf8cf68978d7c2d106c5f67c32 100644 (file)
@@ -34,7 +34,7 @@
                        };
 
                        spi0: spi@f0004000 {
-                               cs-gpios = <&pioD 13 0>;
+                               cs-gpios = <&pioD 13 0>, <0>, <0>, <&pioD 16 0>;
                                status = "okay";
                        };
 
@@ -79,7 +79,7 @@
                        };
 
                        spi1: spi@f8008000 {
-                               cs-gpios = <&pioC 25 0>, <0>, <0>, <&pioD 16 0>;
+                               cs-gpios = <&pioC 25 0>;
                                status = "okay";
                        };
 
index 366fc2cbcd64c3f56495d104e5a744315c7c4345..c0e0eae16a279f65dfc979d5d10735ca5b097c38 100644 (file)
                                trigger@3 {
                                        reg = <3>;
                                        trigger-name = "external";
-                                       trigger-value = <0x13>;
+                                       trigger-value = <0xd>;
                                        trigger-external;
                                };
                        };
index e21dda0e8986574b2531c1675eca1b4de164822d..3be973e9889a2b0ef29cc45657ad6eeb056e7f5f 100644 (file)
@@ -10,7 +10,7 @@
 #include <dt-bindings/pinctrl/at91.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/clk/at91.h>
+#include <dt-bindings/clock/at91.h>
 
 / {
        model = "Atmel AT91SAM9261 family SoC";
index 63e1784d272c556974023fcfd7d46ba7a0510e3d..92a52faebef77cd8eda572d11504c0f83362a428 100644 (file)
@@ -8,7 +8,7 @@
 
 #include "skeleton.dtsi"
 #include <dt-bindings/pinctrl/at91.h>
-#include <dt-bindings/clk/at91.h>
+#include <dt-bindings/clock/at91.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/gpio/gpio.h>
 
index 9583563dd0ef7a3f0d4cd89765a20bb243b10117..8a558b7ac99980b0c3ec2c50dc791341f70028c8 100644 (file)
                status = "okay";
 
                ak8975@0c {
-                       compatible = "ak,ak8975";
+                       compatible = "asahi-kasei,ak8975";
                        reg = <0x0c>;
                        gpios = <&gpj0 7 0>;
                };
index 090f9830b129b72259e4976be890917182b8a6f5..cde19c818667a50170bbd8562a3a943f05df619f 100644 (file)
                                        regulator-name = "VDD_IOPERI_1.8V";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
                                        op_mode = <1>;
                                };
 
index 80a3bf4c59865e0403a4197abb5ae6f0bc00d363..896a2a6619e0a72aed8c0f474c721e8294a38a3d 100644 (file)
                        gpio-key,wakeup;
                };
        };
-
-       amba {
-               mdma1: mdma@11C10000 {
-                       /*
-                        * MDMA1 can support both secure and non-secure
-                        * AXI transactions. When this is enabled in the kernel
-                        * for boards that run in secure mode, we are getting
-                        * imprecise external aborts causing the kernel to oops.
-                        */
-                       status = "disabled";
-               };
-       };
 };
index c3a9a66c57678f9a5dddd75e11e55be913e3c3c0..b69fbcb7dcb8accc3fc2f7abd713dc754b9fd5ad 100644 (file)
                reg = <0x100440C0 0x20>;
        };
 
-       mau_pd: power-domain@100440E0 {
-               compatible = "samsung,exynos4210-pd";
-               reg = <0x100440E0 0x20>;
-       };
-
-       g2d_pd: power-domain@10044100 {
-               compatible = "samsung,exynos4210-pd";
-               reg = <0x10044100 0x20>;
-       };
-
        msc_pd: power-domain@10044120 {
                compatible = "samsung,exynos4210-pd";
                reg = <0x10044120 0x20>;
                        #dma-cells = <1>;
                        #dma-channels = <8>;
                        #dma-requests = <1>;
+                       /*
+                        * MDMA1 can support both secure and non-secure
+                        * AXI transactions. When this is enabled in the kernel
+                        * for boards that run in secure mode, we are getting
+                        * imprecise external aborts causing the kernel to oops.
+                        */
+                       status = "disabled";
                };
        };
 
        spi_0: spi@12d20000 {
                compatible = "samsung,exynos4210-spi";
                reg = <0x12d20000 0x100>;
-               interrupts = <0 66 0>;
+               interrupts = <0 68 0>;
                dmas = <&pdma0 5
                        &pdma0 4>;
                dma-names = "tx", "rx";
        spi_1: spi@12d30000 {
                compatible = "samsung,exynos4210-spi";
                reg = <0x12d30000 0x100>;
-               interrupts = <0 67 0>;
+               interrupts = <0 69 0>;
                dmas = <&pdma1 5
                        &pdma1 4>;
                dma-names = "tx", "rx";
        spi_2: spi@12d40000 {
                compatible = "samsung,exynos4210-spi";
                reg = <0x12d40000 0x100>;
-               interrupts = <0 68 0>;
+               interrupts = <0 70 0>;
                dmas = <&pdma0 7
                        &pdma0 6>;
                dma-names = "tx", "rx";
                interrupts = <0 112 0>;
                clocks = <&clock 471>;
                clock-names = "secss";
-               samsung,power-domain = <&g2d_pd>;
        };
 };
index 7c8c129698929151512f282c5baad14c69f51309..a3431d7848709aac0463a27e4471c22dd17a4a46 100644 (file)
 &tve {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_vga_sync_1>;
-       i2c-ddc-bus = <&i2c3>;
+       ddc-i2c-bus = <&i2c3>;
        fsl,tve-mode = "vga";
        fsl,hsync-pin = <4>;
        fsl,vsync-pin = <6>;
index 9c2bff2252d0d078514348ab2bc92aad7ea5a6fb..6a1bf4ff83d5516dac0016ebc2bdd21d05565631 100644 (file)
                        #address-cells = <1>;
                        #size-cells = <0>;
                        compatible = "fsl,imx53-ipu";
-                       reg = <0x18000000 0x080000000>;
+                       reg = <0x18000000 0x08000000>;
                        interrupts = <11 10>;
                        clocks = <&clks IMX5_CLK_IPU_GATE>,
                                 <&clks IMX5_CLK_IPU_DI0_GATE>,
index 32c6fb4a11624c05756e4e2fe24b05c62c799667..b939f4f52d16a7c0edb677a86558bacd94fec831 100644 (file)
                bootargs = "console=ttyS0,115200n8 earlyprintk";
        };
 
+       mbus {
+               pcie-controller {
+                       status = "okay";
+
+                       pcie@1,0 {
+                               status = "okay";
+                       };
+               };
+        };
+
        ocp@f1000000 {
                pinctrl@10000 {
                        pmx_usb_led: pmx-usb-led {
                ehci@50000 {
                        status = "okay";
                };
-
-               pcie-controller {
-                       status = "okay";
-
-                       pcie@1,0 {
-                               status = "okay";
-                       };
-               };
        };
 
        gpio-leds {
index aa78c2d11fe738fc843f716bd1a6f98ff1054a5b..e2cc85cc3b87e805a113489d3d95cf912d682224 100644 (file)
@@ -4,6 +4,16 @@
 / {
        model = "ZyXEL NSA310";
 
+       mbus {
+               pcie-controller {
+                       status = "okay";
+
+                       pcie@1,0 {
+                               status = "okay";
+                       };
+               };
+       };
+
        ocp@f1000000 {
                pinctrl: pinctrl@10000 {
 
                        status = "okay";
                        nr-ports = <2>;
                };
-
-               pcie-controller {
-                       status = "okay";
-
-                       pcie@1,0 {
-                               status = "okay";
-                       };
-               };
        };
 
        gpio_poweroff {
index 7d1c7677a18f18c3fb1cc00463420545a5b6cb78..0bd70d928c69ba7f7798d1492f6ce3844af9d6ad 100644 (file)
 
                i2c@11000 {
                        status = "okay";
-
-                       alc5621: alc5621@1a {
-                               compatible = "realtek,alc5621";
-                               reg = <0x1a>;
-                       };
                };
 
                serial@12000 {
index f577b7df9a29e4f5f4e74ca86aef4b4ba61ceb87..521c587acaee9f679ab6f9200c5f8be8eee240e9 100644 (file)
                compatible = "smsc,lan9221", "smsc,lan9115";
                bank-width = <2>;
                gpmc,mux-add-data;
-               gpmc,cs-on-ns = <0>;
-               gpmc,cs-rd-off-ns = <186>;
-               gpmc,cs-wr-off-ns = <186>;
-               gpmc,adv-on-ns = <12>;
-               gpmc,adv-rd-off-ns = <48>;
+               gpmc,cs-on-ns = <1>;
+               gpmc,cs-rd-off-ns = <180>;
+               gpmc,cs-wr-off-ns = <180>;
+               gpmc,adv-rd-off-ns = <18>;
                gpmc,adv-wr-off-ns = <48>;
                gpmc,oe-on-ns = <54>;
                gpmc,oe-off-ns = <168>;
                gpmc,we-off-ns = <168>;
                gpmc,rd-cycle-ns = <186>;
                gpmc,wr-cycle-ns = <186>;
-               gpmc,access-ns = <114>;
-               gpmc,page-burst-access-ns = <6>;
-               gpmc,bus-turnaround-ns = <12>;
-               gpmc,cycle2cycle-delay-ns = <18>;
-               gpmc,wr-data-mux-bus-ns = <90>;
-               gpmc,wr-access-ns = <186>;
+               gpmc,access-ns = <144>;
+               gpmc,page-burst-access-ns = <24>;
+               gpmc,bus-turnaround-ns = <90>;
+               gpmc,cycle2cycle-delay-ns = <90>;
                gpmc,cycle2cycle-samecsen;
                gpmc,cycle2cycle-diffcsen;
                vddvario-supply = <&vddvario>;
index 22f35ea142c199082afdd8ba626bd7c5e0b6cd54..8f8c07da4ac148d550ae45cd3501d4a992f4e7c8 100644 (file)
                        interrupts = <58>;
                };
 
-               mailbox: mailbox@48094000 {
-                       compatible = "ti,omap2-mailbox";
-                       ti,hwmods = "mailbox";
-                       reg = <0x48094000 0x200>;
-                       interrupts = <26>;
-               };
-
                intc: interrupt-controller@1 {
                        compatible = "ti,omap2-intc";
                        interrupt-controller;
index 85b1fb014c4314efe82eca9fcb7dfa7e482cb8d2..2d9979835f241f2153cd3d0b52c5c8b0b6c49559 100644 (file)
                        dma-names = "tx", "rx";
                };
 
+               mailbox: mailbox@48094000 {
+                       compatible = "ti,omap2-mailbox";
+                       reg = <0x48094000 0x200>;
+                       interrupts = <26>, <34>;
+                       interrupt-names = "dsp", "iva";
+                       ti,hwmods = "mailbox";
+               };
+
                timer1: timer@48028000 {
                        compatible = "ti,omap2420-timer";
                        reg = <0x48028000 0x400>;
index d09697dab55e80063a737361c65138822bbdf828..42d2c61c9e2d7dc1851054a45ec305820cc8a9f4 100644 (file)
                        dma-names = "tx", "rx";
                };
 
+               mailbox: mailbox@48094000 {
+                       compatible = "ti,omap2-mailbox";
+                       reg = <0x48094000 0x200>;
+                       interrupts = <26>;
+                       ti,hwmods = "mailbox";
+               };
+
                timer1: timer@49018000 {
                        compatible = "ti,omap2420-timer";
                        reg = <0x49018000 0x400>;
index d00055809e31d79b9d1730c06efe02c7e2e6f747..25ba08331d8852e6701c96a4b9e8e54def19f0d8 100644 (file)
                        cpu0-supply = <&vcc>;
                };
        };
-
-       vddvario: regulator-vddvario {
-               compatible = "regulator-fixed";
-               regulator-name = "vddvario";
-               regulator-always-on;
-       };
-
-       vdd33a: regulator-vdd33a {
-               compatible = "regulator-fixed";
-               regulator-name = "vdd33a";
-               regulator-always-on;
-       };
 };
 
 &omap3_pmx_core {
 
        hsusb0_pins: pinmux_hsusb0_pins {
                pinctrl-single,pins = <
-                       OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0)               /* hsusb0_clk.hsusb0_clk */
-                       OMAP3_CORE1_IOPAD(0x21a2, PIN_OUTPUT | MUX_MODE0)               /* hsusb0_stp.hsusb0_stp */
-                       OMAP3_CORE1_IOPAD(0x21a4, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_dir.hsusb0_dir */
-                       OMAP3_CORE1_IOPAD(0x21a6, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_nxt.hsusb0_nxt */
-                       OMAP3_CORE1_IOPAD(0x21a8, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_data0.hsusb2_data0 */
-                       OMAP3_CORE1_IOPAD(0x21aa, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_data1.hsusb0_data1 */
-                       OMAP3_CORE1_IOPAD(0x21ac, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_data2.hsusb0_data2 */
-                       OMAP3_CORE1_IOPAD(0x21ae, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_data7.hsusb0_data3 */
-                       OMAP3_CORE1_IOPAD(0x21b0, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_data7.hsusb0_data4 */
-                       OMAP3_CORE1_IOPAD(0x21b2, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_data7.hsusb0_data5 */
-                       OMAP3_CORE1_IOPAD(0x21b4, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_data7.hsusb0_data6 */
-                       OMAP3_CORE1_IOPAD(0x21b6, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_data7.hsusb0_data7 */
+                       OMAP3_CORE1_IOPAD(0x21a2, PIN_OUTPUT | MUX_MODE0)               /* hsusb0_clk.hsusb0_clk */
+                       OMAP3_CORE1_IOPAD(0x21a4, PIN_OUTPUT | MUX_MODE0)               /* hsusb0_stp.hsusb0_stp */
+                       OMAP3_CORE1_IOPAD(0x21a6, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_dir.hsusb0_dir */
+                       OMAP3_CORE1_IOPAD(0x21a8, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_nxt.hsusb0_nxt */
+                       OMAP3_CORE1_IOPAD(0x21aa, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_data0.hsusb2_data0 */
+                       OMAP3_CORE1_IOPAD(0x21ac, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_data1.hsusb0_data1 */
+                       OMAP3_CORE1_IOPAD(0x21ae, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_data2.hsusb0_data2 */
+                       OMAP3_CORE1_IOPAD(0x21b0, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_data7.hsusb0_data3 */
+                       OMAP3_CORE1_IOPAD(0x21b2, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_data7.hsusb0_data4 */
+                       OMAP3_CORE1_IOPAD(0x21b4, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_data7.hsusb0_data5 */
+                       OMAP3_CORE1_IOPAD(0x21b6, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_data7.hsusb0_data6 */
+                       OMAP3_CORE1_IOPAD(0x21b8, PIN_INPUT_PULLDOWN | MUX_MODE0)       /* hsusb0_data7.hsusb0_data7 */
                >;
        };
 };
 
+#include "omap-gpmc-smsc911x.dtsi"
+
 &gpmc {
        ranges = <5 0 0x2c000000 0x01000000>;
 
-       smsc1: ethernet@5,0 {
+       smsc1: ethernet@gpmc {
                compatible = "smsc,lan9221", "smsc,lan9115";
                pinctrl-names = "default";
                pinctrl-0 = <&smsc1_pins>;
                interrupt-parent = <&gpio6>;
                interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
                reg = <5 0 0xff>;
-               bank-width = <2>;
-               gpmc,mux-add-data;
-               gpmc,cs-on-ns = <0>;
-               gpmc,cs-rd-off-ns = <186>;
-               gpmc,cs-wr-off-ns = <186>;
-               gpmc,adv-on-ns = <12>;
-               gpmc,adv-rd-off-ns = <48>;
-               gpmc,adv-wr-off-ns = <48>;
-               gpmc,oe-on-ns = <54>;
-               gpmc,oe-off-ns = <168>;
-               gpmc,we-on-ns = <54>;
-               gpmc,we-off-ns = <168>;
-               gpmc,rd-cycle-ns = <186>;
-               gpmc,wr-cycle-ns = <186>;
-               gpmc,access-ns = <114>;
-               gpmc,page-burst-access-ns = <6>;
-               gpmc,bus-turnaround-ns = <12>;
-               gpmc,cycle2cycle-delay-ns = <18>;
-               gpmc,wr-data-mux-bus-ns = <90>;
-               gpmc,wr-access-ns = <186>;
-               gpmc,cycle2cycle-samecsen;
-               gpmc,cycle2cycle-diffcsen;
-               vddvario-supply = <&vddvario>;
-               vdd33a-supply = <&vdd33a>;
-               reg-io-width = <4>;
-               smsc,save-mac-address;
        };
 };
 
index b97736d98a6427f087c11bd510909b1007f8c152..e2d163bf061975bff9ac5a6e83ecf6bf4ef98ed3 100644 (file)
                >;
        };
 
-       smsc911x_pins: pinmux_smsc911x_pins {
+       smsc9221_pins: pinmux_smsc9221_pins {
                pinctrl-single,pins = <
                        0x1a2 (PIN_INPUT | MUX_MODE4)           /* mcspi1_cs2.gpio_176 */
                >;
index 7abd64f6ae21465c9ac74b22563f8f828a5d684b..b22caaaf774ba710461fcabf395c121c0ccc0482 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 #include "omap3-igep.dtsi"
-#include "omap-gpmc-smsc911x.dtsi"
+#include "omap-gpmc-smsc9221.dtsi"
 
 / {
        model = "IGEPv2 (TI OMAP AM/DM37x)";
 
        ethernet@gpmc {
                pinctrl-names = "default";
-               pinctrl-0 = <&smsc911x_pins>;
+               pinctrl-0 = <&smsc9221_pins>;
                reg = <5 0 0xff>;
                interrupt-parent = <&gpio6>;
                interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
index 7909c51b05a5643563b4ed74405066e1a222a995..d59e3de1441e2f7dc5e0fb9b4bc29f49ee04cbc1 100644 (file)
@@ -2,20 +2,6 @@
  * Common support for CompuLab SB-T35 used on SBC-T3530, SBC-T3517 and SBC-T3730
  */
 
-/ {
-       vddvario_sb_t35: regulator-vddvario-sb-t35 {
-               compatible = "regulator-fixed";
-               regulator-name = "vddvario";
-               regulator-always-on;
-       };
-
-       vdd33a_sb_t35: regulator-vdd33a-sb-t35 {
-               compatible = "regulator-fixed";
-               regulator-name = "vdd33a";
-               regulator-always-on;
-       };
-};
-
 &omap3_pmx_core {
        smsc2_pins: pinmux_smsc2_pins {
                pinctrl-single,pins = <
                reg = <4 0 0xff>;
                bank-width = <2>;
                gpmc,mux-add-data;
-               gpmc,cs-on-ns = <0>;
-               gpmc,cs-rd-off-ns = <186>;
-               gpmc,cs-wr-off-ns = <186>;
-               gpmc,adv-on-ns = <12>;
-               gpmc,adv-rd-off-ns = <48>;
+               gpmc,cs-on-ns = <1>;
+               gpmc,cs-rd-off-ns = <180>;
+               gpmc,cs-wr-off-ns = <180>;
+               gpmc,adv-rd-off-ns = <18>;
                gpmc,adv-wr-off-ns = <48>;
                gpmc,oe-on-ns = <54>;
                gpmc,oe-off-ns = <168>;
                gpmc,we-off-ns = <168>;
                gpmc,rd-cycle-ns = <186>;
                gpmc,wr-cycle-ns = <186>;
-               gpmc,access-ns = <114>;
-               gpmc,page-burst-access-ns = <6>;
-               gpmc,bus-turnaround-ns = <12>;
-               gpmc,cycle2cycle-delay-ns = <18>;
-               gpmc,wr-data-mux-bus-ns = <90>;
-               gpmc,wr-access-ns = <186>;
+               gpmc,access-ns = <144>;
+               gpmc,page-burst-access-ns = <24>;
+               gpmc,bus-turnaround-ns = <90>;
+               gpmc,cycle2cycle-delay-ns = <90>;
                gpmc,cycle2cycle-samecsen;
                gpmc,cycle2cycle-diffcsen;
-               vddvario-supply = <&vddvario_sb_t35>;
-               vdd33a-supply = <&vdd33a_sb_t35>;
+               vddvario-supply = <&vddvario>;
+               vdd33a-supply = <&vdd33a>;
                reg-io-width = <4>;
                smsc,save-mac-address;
        };
index 024c9c6c682d7eb4b421a559c7c4b5f95e0511f9..42189b65d393d29d2cf467ddbc5df4eb0661a471 100644 (file)
@@ -8,6 +8,19 @@
 / {
        model = "CompuLab SBC-T3517 with CM-T3517";
        compatible = "compulab,omap3-sbc-t3517", "compulab,omap3-cm-t3517", "ti,am3517", "ti,omap3";
+
+       /* Only one GPMC smsc9220 on SBC-T3517, CM-T3517 uses am35x Ethernet */
+       vddvario: regulator-vddvario-sb-t35 {
+               compatible = "regulator-fixed";
+               regulator-name = "vddvario";
+               regulator-always-on;
+       };
+
+       vdd33a: regulator-vdd33a-sb-t35 {
+               compatible = "regulator-fixed";
+               regulator-name = "vdd33a";
+               regulator-always-on;
+       };
 };
 
 &omap3_pmx_core {
index acb9019dc437b66321ec7995dc16456678a2e42c..4231191ade06acf8c7a02938a0fcfcbdeb318fbc 100644 (file)
@@ -61,7 +61,7 @@
                        ti,hwmods = "mpu";
                };
 
-               iva {
+               iva: iva {
                        compatible = "ti,iva2.2";
                        ti,hwmods = "iva";
 
index f8c9855ce587c15790f79a2f04e0ff02933f463f..36b4312a5e0d82fb20fb6a7eb9b1d59942b0ec18 100644 (file)
                        status = "disabled";
                };
 
+               mailbox: mailbox@4a0f4000 {
+                       compatible = "ti,omap4-mailbox";
+                       reg = <0x4a0f4000 0x200>;
+                       interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+                       ti,hwmods = "mailbox";
+               };
+
                timer1: timer@4ae18000 {
                        compatible = "ti,omap5430-timer";
                        reg = <0x4ae18000 0x80>;
index eabcfdbb403acc7ff40b409617a53c9831414c04..a106b0872910da874f1000f417a1aab1793237de 100644 (file)
@@ -13,7 +13,7 @@
 #include <dt-bindings/pinctrl/at91.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/clk/at91.h>
+#include <dt-bindings/clock/at91.h>
 
 / {
        model = "Atmel SAMA5D3 family SoC";
index b029fe7ef17a657946de4d2fe71168b4b03210d8..1b02208ea6ff2b70aab43ddd416b37ef0b9a2a1f 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <dt-bindings/pinctrl/at91.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/clk/at91.h>
+#include <dt-bindings/clock/at91.h>
 
 / {
        ahb {
index 382b04431f66b621e01a9f2fe7a9e488ac4c171b..02848453ca0cf5447de27aaca6b233611173da4e 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <dt-bindings/pinctrl/at91.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/clk/at91.h>
+#include <dt-bindings/clock/at91.h>
 
 / {
        aliases {
index a9fa75e4165205f9a1259f9a0821519faee54070..7a8d4c6115f72fdab533980a0f0d96eb6cb1469a 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <dt-bindings/pinctrl/at91.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/clk/at91.h>
+#include <dt-bindings/clock/at91.h>
 
 / {
        aliases {
index 7f3baf51a3a9e933d3a47dce18d2ca102c104a9b..32dd55e5f4e6b8567a8a2d207b69311959c9f9a1 100644 (file)
@@ -18,6 +18,7 @@
        compatible = "st-ericsson,ccu8540", "st-ericsson,u8540";
 
        memory@0 {
+               device_type = "memory";
                reg = <0x20000000 0x1f000000>, <0xc0000000 0x3f000000>;
        };
 
index 32efc105df834de3c3143938bf0cfdebbf5d1b55..aba1c8a3f3883320a50b31dcac05341568e0a335 100644 (file)
@@ -87,7 +87,7 @@
 
                pll4: clk@01c20018 {
                        #clock-cells = <0>;
-                       compatible = "allwinner,sun4i-a10-pll1-clk";
+                       compatible = "allwinner,sun7i-a20-pll4-clk";
                        reg = <0x01c20018 0x4>;
                        clocks = <&osc24M>;
                        clock-output-names = "pll4";
                        clock-output-names = "pll6_sata", "pll6_other", "pll6";
                };
 
+               pll8: clk@01c20040 {
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun7i-a20-pll4-clk";
+                       reg = <0x01c20040 0x4>;
+                       clocks = <&osc24M>;
+                       clock-output-names = "pll8";
+               };
+
                cpu: cpu@01c20054 {
                        #clock-cells = <0>;
                        compatible = "allwinner,sun4i-a10-cpu-clk";
                        status = "disabled";
                };
 
-               i2c4: i2c@01c2bc00 {
+               i2c4: i2c@01c2c000 {
                        compatible = "allwinner,sun4i-i2c";
-                       reg = <0x01c2bc00 0x400>;
+                       reg = <0x01c2c000 0x400>;
                        interrupts = <0 89 4>;
                        clocks = <&apb1_gates 15>;
                        clock-frequency = <100000>;
index f01c0ee0c87ebd94debc320f5714bf247dfe5ab7..490f3dced749956d6f63f94ba74cebc6f55a4964 100644 (file)
@@ -433,8 +433,12 @@ static void bL_switcher_restore_cpus(void)
 {
        int i;
 
-       for_each_cpu(i, &bL_switcher_removed_logical_cpus)
-               cpu_up(i);
+       for_each_cpu(i, &bL_switcher_removed_logical_cpus) {
+               struct device *cpu_dev = get_cpu_device(i);
+               int ret = device_online(cpu_dev);
+               if (ret)
+                       dev_err(cpu_dev, "switcher: unable to restore CPU\n");
+       }
 }
 
 static int bL_switcher_halve_cpus(void)
@@ -521,7 +525,7 @@ static int bL_switcher_halve_cpus(void)
                        continue;
                }
 
-               ret = cpu_down(i);
+               ret = device_offline(get_cpu_device(i));
                if (ret) {
                        bL_switcher_restore_cpus();
                        return ret;
index 41bca32409fce81358c3b5c35bc081bcc28e7c76..5339009b3c0ce648df92244b5d9274e78273290b 100644 (file)
@@ -1423,55 +1423,38 @@ EXPORT_SYMBOL(edma_clear_event);
 
 #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DMADEVICES)
 
-static int edma_of_read_u32_to_s16_array(const struct device_node *np,
-                                        const char *propname, s16 *out_values,
-                                        size_t sz)
+static int edma_xbar_event_map(struct device *dev, struct device_node *node,
+                              struct edma_soc_info *pdata, size_t sz)
 {
-       int ret;
-
-       ret = of_property_read_u16_array(np, propname, out_values, sz);
-       if (ret)
-               return ret;
-
-       /* Terminate it */
-       *out_values++ = -1;
-       *out_values++ = -1;
-
-       return 0;
-}
-
-static int edma_xbar_event_map(struct device *dev,
-                              struct device_node *node,
-                              struct edma_soc_info *pdata, int len)
-{
-       int ret, i;
+       const char pname[] = "ti,edma-xbar-event-map";
        struct resource res;
        void __iomem *xbar;
-       const s16 (*xbar_chans)[2];
+       s16 (*xbar_chans)[2];
+       size_t nelm = sz / sizeof(s16);
        u32 shift, offset, mux;
+       int ret, i;
 
-       xbar_chans = devm_kzalloc(dev,
-                                 len/sizeof(s16) + 2*sizeof(s16),
-                                 GFP_KERNEL);
+       xbar_chans = devm_kzalloc(dev, (nelm + 2) * sizeof(s16), GFP_KERNEL);
        if (!xbar_chans)
                return -ENOMEM;
 
        ret = of_address_to_resource(node, 1, &res);
        if (ret)
-               return -EIO;
+               return -ENOMEM;
 
        xbar = devm_ioremap(dev, res.start, resource_size(&res));
        if (!xbar)
                return -ENOMEM;
 
-       ret = edma_of_read_u32_to_s16_array(node,
-                                           "ti,edma-xbar-event-map",
-                                           (s16 *)xbar_chans,
-                                           len/sizeof(u32));
+       ret = of_property_read_u16_array(node, pname, (u16 *)xbar_chans, nelm);
        if (ret)
                return -EIO;
 
-       for (i = 0; xbar_chans[i][0] != -1; i++) {
+       /* Invalidate last entry for the other user of this mess */
+       nelm >>= 1;
+       xbar_chans[nelm][0] = xbar_chans[nelm][1] = -1;
+
+       for (i = 0; i < nelm; i++) {
                shift = (xbar_chans[i][1] & 0x03) << 3;
                offset = xbar_chans[i][1] & 0xfffffffc;
                mux = readl(xbar + offset);
@@ -1480,8 +1463,7 @@ static int edma_xbar_event_map(struct device *dev,
                writel(mux, (xbar + offset));
        }
 
-       pdata->xbar_chans = xbar_chans;
-
+       pdata->xbar_chans = (const s16 (*)[2]) xbar_chans;
        return 0;
 }
 
index 4ce7b70ea9011634de2bcb9f1b0ff4f29e046ecd..e07a227ec0dbb331bae2428427dc36fec444adec 100644 (file)
@@ -65,6 +65,7 @@ CONFIG_TCG_TIS_I2C_INFINEON=y
 CONFIG_I2C=y
 CONFIG_I2C_MUX=y
 CONFIG_I2C_ARB_GPIO_CHALLENGE=y
+CONFIG_I2C_EXYNOS5=y
 CONFIG_I2C_S3C2410=y
 CONFIG_DEBUG_GPIO=y
 # CONFIG_HWMON is not set
index b5df4a511b0acdfea6df30b7dd4b9753d2b00f9a..81ba78eaf54adb02840dbc2d41cc4af8acc7c08a 100644 (file)
@@ -37,7 +37,7 @@ CONFIG_SUN4I_EMAC=y
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_SMSC is not set
-# CONFIG_NET_VENDOR_STMICRO is not set
+CONFIG_STMMAC_ETH=y
 # CONFIG_NET_VENDOR_WIZNET is not set
 # CONFIG_WLAN is not set
 CONFIG_SERIAL_8250=y
index b5f7705abcb024bb21c41ce34c6f7e95ddfb9bb8..624e1d436c6ce8d387bef77963c1315bc702a938 100644 (file)
@@ -54,7 +54,9 @@ static inline void register_trusted_foundations(
         */
        pr_err("No support for Trusted Foundations, continuing in degraded mode.\n");
        pr_err("Secondary processors as well as CPU PM will be disabled.\n");
+#if IS_ENABLED(CONFIG_SMP)
        setup_max_cpus = 0;
+#endif
        cpu_idle_poll_ctrl(true);
 }
 
index 12c3a5decc609d882626ec75bb2e82ebcbb74030..75d95799b6e6df7238dd425dc66da51ddb006633 100644 (file)
@@ -171,8 +171,9 @@ extern int __put_user_8(void *, unsigned long long);
 #define __put_user_check(x,p)                                                  \
        ({                                                              \
                unsigned long __limit = current_thread_info()->addr_limit - 1; \
+               const typeof(*(p)) __user *__tmp_p = (p);               \
                register const typeof(*(p)) __r2 asm("r2") = (x);       \
-               register const typeof(*(p)) __user *__p asm("r0") = (p);\
+               register const typeof(*(p)) __user *__p asm("r0") = __tmp_p; \
                register unsigned long __l asm("r1") = __limit;         \
                register int __e asm("r0");                             \
                switch (sizeof(*(__p))) {                               \
index 7704e28c348393377b76cf8319a89ca2f413e03f..712b50e0a6dc6901a5507ac89eeeeabdfefe4f19 100644 (file)
@@ -34,6 +34,7 @@
 #define _ASM_ARM_XEN_HYPERCALL_H
 
 #include <xen/interface/xen.h>
+#include <xen/interface/sched.h>
 
 long privcmd_call(unsigned call, unsigned long a1,
                unsigned long a2, unsigned long a3,
@@ -48,6 +49,16 @@ int HYPERVISOR_memory_op(unsigned int cmd, void *arg);
 int HYPERVISOR_physdev_op(int cmd, void *arg);
 int HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args);
 int HYPERVISOR_tmem_op(void *arg);
+int HYPERVISOR_multicall(struct multicall_entry *calls, uint32_t nr);
+
+static inline int
+HYPERVISOR_suspend(unsigned long start_info_mfn)
+{
+       struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
+
+       /* start_info_mfn is unused on ARM */
+       return HYPERVISOR_sched_op(SCHEDOP_shutdown, &r);
+}
 
 static inline void
 MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
@@ -63,9 +74,4 @@ MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
        BUG();
 }
 
-static inline int
-HYPERVISOR_multicall(void *call_list, int nr_calls)
-{
-       BUG();
-}
 #endif /* _ASM_ARM_XEN_HYPERCALL_H */
index 1151188bcd83c391c0ba0ca3d51b4b32226aa4be..50066006e6bd3a961a580720911ab9c224f2fa36 100644 (file)
@@ -40,6 +40,8 @@ typedef uint64_t xen_pfn_t;
 #define PRI_xen_pfn "llx"
 typedef uint64_t xen_ulong_t;
 #define PRI_xen_ulong "llx"
+typedef int64_t xen_long_t;
+#define PRI_xen_long "llx"
 /* Guest handles for primitive C types. */
 __DEFINE_GUEST_HANDLE(uchar, unsigned char);
 __DEFINE_GUEST_HANDLE(uint,  unsigned int);
index cf4f3e867395ef0261b16a4d721d8cff740c1de2..ded062f9b358038c05fa074816706c40619e6408 100644 (file)
@@ -77,7 +77,6 @@ static inline xpaddr_t machine_to_phys(xmaddr_t machine)
 }
 /* VIRT <-> MACHINE conversion */
 #define virt_to_machine(v)     (phys_to_machine(XPADDR(__pa(v))))
-#define virt_to_pfn(v)          (PFN_DOWN(__pa(v)))
 #define virt_to_mfn(v)         (pfn_to_mfn(virt_to_pfn(v)))
 #define mfn_to_virt(m)         (__va(mfn_to_pfn(m) << PAGE_SHIFT))
 
index 1420725142cab1817d26bc3ff7003ae4a4833732..efb208de75ec55067882afb0b2be768b78637a54 100644 (file)
        orrne   r5, V7M_xPSR_FRAMEPTRALIGN
        biceq   r5, V7M_xPSR_FRAMEPTRALIGN
 
+       @ ensure bit 0 is cleared in the PC, otherwise behaviour is
+       @ unpredictable
+       bic     r4, #1
+
        @ write basic exception frame
        stmdb   r2!, {r1, r3-r5}
        ldmia   sp, {r1, r3-r5}
index 3c217694ebecb126b23f226688bcc6874b0c8c7b..cb791ac6a0037dfd392622eb5adf24467bcedc37 100644 (file)
@@ -285,7 +285,7 @@ static int unwind_exec_pop_r4_to_rN(struct unwind_ctrl_block *ctrl,
                if (unwind_pop_register(ctrl, &vsp, reg))
                                return -URC_FAILURE;
 
-       if (insn & 0x80)
+       if (insn & 0x8)
                if (unwind_pop_register(ctrl, &vsp, 14))
                                return -URC_FAILURE;
 
index a0282928e9c10bdbc67b385423b225f8e5315756..7cd6f19945ed737198f50f04db777348e9e7a3b8 100644 (file)
@@ -1308,19 +1308,19 @@ static struct platform_device at91_adc_device = {
 static struct at91_adc_trigger at91_adc_triggers[] = {
        [0] = {
                .name = "timer-counter-0",
-               .value = AT91_ADC_TRGSEL_TC0 | AT91_ADC_TRGEN,
+               .value = 0x1,
        },
        [1] = {
                .name = "timer-counter-1",
-               .value = AT91_ADC_TRGSEL_TC1 | AT91_ADC_TRGEN,
+               .value = 0x3,
        },
        [2] = {
                .name = "timer-counter-2",
-               .value = AT91_ADC_TRGSEL_TC2 | AT91_ADC_TRGEN,
+               .value = 0x5,
        },
        [3] = {
                .name = "external",
-               .value = AT91_ADC_TRGSEL_EXTERNAL | AT91_ADC_TRGEN,
+               .value = 0xd,
                .is_external = true,
        },
 };
index 932129ef26c66054a2bdeecaef9c0af1a9bba788..aa01c4222b40334db58a603cbcbee82f5f671d6b 100644 (file)
@@ -18,6 +18,8 @@
 
 #include <mach/map.h>
 
+#include <plat/cpu.h>
+
 #include "smc.h"
 
 static int exynos_do_idle(void)
@@ -28,13 +30,24 @@ static int exynos_do_idle(void)
 
 static int exynos_cpu_boot(int cpu)
 {
+       /*
+        * The second parameter of SMC_CMD_CPU1BOOT command means CPU id.
+        * But, Exynos4212 has only one secondary CPU so second parameter
+        * isn't used for informing secure firmware about CPU id.
+        */
+       if (soc_is_exynos4212())
+               cpu = 0;
+
        exynos_smc(SMC_CMD_CPU1BOOT, cpu, 0, 0);
        return 0;
 }
 
 static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
 {
-       void __iomem *boot_reg = S5P_VA_SYSRAM_NS + 0x1c + 4*cpu;
+       void __iomem *boot_reg = S5P_VA_SYSRAM_NS + 0x1c;
+
+       if (!soc_is_exynos4212())
+               boot_reg += 4*cpu;
 
        __raw_writel(boot_addr, boot_reg);
        return 0;
index fc4dd7cedc1189019dea590e8a4caa6b0ebf6884..6bd7c3f37ac08e139118e48f200a075cb9fbac8b 100644 (file)
@@ -77,7 +77,7 @@ struct platform_device *__init imx_alloc_mx3_camera(
 
        pdev = platform_device_alloc("mx3-camera", 0);
        if (!pdev)
-               goto err;
+               return ERR_PTR(-ENOMEM);
 
        pdev->dev.dma_mask = kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
        if (!pdev->dev.dma_mask)
index f3d4cf53f7466ba6c44f5ef1d91484e3ce8f62e6..09520e19b78e46d441e288001d923448b2cd0995 100644 (file)
@@ -108,7 +108,18 @@ static int __init mvebu_soc_id_init(void)
        iounmap(pci_base);
 
 res_ioremap:
-       clk_disable_unprepare(clk);
+       /*
+        * If the PCIe unit is actually enabled and we have PCI
+        * support in the kernel, we intentionally do not release the
+        * reference to the clock. We want to keep it running since
+        * the bootloader does some PCIe link configuration that the
+        * kernel is for now unable to do, and gating the clock would
+        * make us loose this precious configuration.
+        */
+       if (!of_device_is_available(child) || !IS_ENABLED(CONFIG_PCI_MVEBU)) {
+               clk_disable_unprepare(clk);
+               clk_put(clk);
+       }
 
 clk_err:
        of_node_put(child);
index ac82512b9c8c641e044596f737cbe3a518eefe74..b6885e42c0a0749279cdac1babd1e0825f23742a 100644 (file)
@@ -142,7 +142,7 @@ __init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
        board_nand_data.nr_parts        = nr_parts;
        board_nand_data.devsize         = nand_type;
 
-       board_nand_data.ecc_opt = OMAP_ECC_BCH8_CODE_HW;
+       board_nand_data.ecc_opt = OMAP_ECC_HAM1_CODE_HW;
        gpmc_nand_init(&board_nand_data, gpmc_t);
 }
 #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
index 8f5121b89688396d1b3fb4551dc55fc0c4395c00..eb8c75ec3b1ac28ad121969fdbbd586bfca69b20 100644 (file)
@@ -456,7 +456,8 @@ static struct clk_hw_omap dpll4_m5x2_ck_hw = {
        .clkdm_name     = "dpll4_clkdm",
 };
 
-DEFINE_STRUCT_CLK(dpll4_m5x2_ck, dpll4_m5x2_ck_parent_names, dpll4_m5x2_ck_ops);
+DEFINE_STRUCT_CLK_FLAGS(dpll4_m5x2_ck, dpll4_m5x2_ck_parent_names,
+                       dpll4_m5x2_ck_ops, CLK_SET_RATE_PARENT);
 
 static struct clk dpll4_m5x2_ck_3630 = {
        .name           = "dpll4_m5x2_ck",
index 01fc710c81818e9d48e2b26ca8742b77b392ff1c..2498ab025fa296416c03494df6070daf456451ee 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
 #include <linux/export.h>
+#include <linux/clockchips.h>
 
 #include <asm/cpuidle.h>
 #include <asm/proc-fns.h>
@@ -83,6 +84,7 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
 {
        struct idle_statedata *cx = state_ptr + index;
        u32 mpuss_can_lose_context = 0;
+       int cpu_id = smp_processor_id();
 
        /*
         * CPU0 has to wait and stay ON until CPU1 is OFF state.
@@ -110,6 +112,8 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
        mpuss_can_lose_context = (cx->mpu_state == PWRDM_POWER_RET) &&
                                 (cx->mpu_logic_state == PWRDM_POWER_OFF);
 
+       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu_id);
+
        /*
         * Call idle CPU PM enter notifier chain so that
         * VFP and per CPU interrupt context is saved.
@@ -165,6 +169,8 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
        if (dev->cpu == 0 && mpuss_can_lose_context)
                cpu_cluster_pm_exit();
 
+       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id);
+
 fail:
        cpuidle_coupled_parallel_barrier(dev, &abort_barrier);
        cpu_done[dev->cpu] = false;
@@ -172,6 +178,16 @@ fail:
        return index;
 }
 
+/*
+ * For each cpu, setup the broadcast timer because local timers
+ * stops for the states above C1.
+ */
+static void omap_setup_broadcast_timer(void *arg)
+{
+       int cpu = smp_processor_id();
+       clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
+}
+
 static struct cpuidle_driver omap4_idle_driver = {
        .name                           = "omap4_idle",
        .owner                          = THIS_MODULE,
@@ -189,8 +205,7 @@ static struct cpuidle_driver omap4_idle_driver = {
                        /* C2 - CPU0 OFF + CPU1 OFF + MPU CSWR */
                        .exit_latency = 328 + 440,
                        .target_residency = 960,
-                       .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED |
-                                CPUIDLE_FLAG_TIMER_STOP,
+                       .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED,
                        .enter = omap_enter_idle_coupled,
                        .name = "C2",
                        .desc = "CPUx OFF, MPUSS CSWR",
@@ -199,8 +214,7 @@ static struct cpuidle_driver omap4_idle_driver = {
                        /* C3 - CPU0 OFF + CPU1 OFF + MPU OSWR */
                        .exit_latency = 460 + 518,
                        .target_residency = 1100,
-                       .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED |
-                                CPUIDLE_FLAG_TIMER_STOP,
+                       .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_COUPLED,
                        .enter = omap_enter_idle_coupled,
                        .name = "C3",
                        .desc = "CPUx OFF, MPUSS OSWR",
@@ -231,5 +245,8 @@ int __init omap4_idle_init(void)
        if (!cpu_clkdm[0] || !cpu_clkdm[1])
                return -ENODEV;
 
+       /* Configure the broadcast timer on each cpu */
+       on_each_cpu(omap_setup_broadcast_timer, NULL, 1);
+
        return cpuidle_register(&omap4_idle_driver, cpu_online_mask);
 }
index 75e92952c18efe3e597791e6798c2ee2ce5969a1..40c5d5f1451cd34b19ebed5e2d58f150f6f4a29d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Secondary CPU startup routine source file.
  *
- * Copyright (C) 2009 Texas Instruments, Inc.
+ * Copyright (C) 2009-2014 Texas Instruments, Inc.
  *
  * Author:
  *      Santosh Shilimkar <santosh.shilimkar@ti.com>
  * code.  This routine also provides a holding flag into which
  * secondary core is held until we're ready for it to initialise.
  * The primary core will update this flag using a hardware
-+ * register AuxCoreBoot0.
+ * register AuxCoreBoot0.
  */
 ENTRY(omap5_secondary_startup)
+.arm
+THUMB( adr     r9, BSYM(wait)  )       @ CPU may be entered in ARM mode.
+THUMB( bx      r9              )       @ If this is a Thumb-2 kernel,
+THUMB( .thumb                  )       @ switch to Thumb now.
 wait:  ldr     r2, =AUX_CORE_BOOT0_PA  @ read from AuxCoreBoot0
        ldr     r0, [r2]
        mov     r0, r0, lsr #5
index 892317294fdc0812965910a05f1d895d4c2a03cd..e829664e6a6ca24d4c76ebac35e9edfe8e87780c 100644 (file)
@@ -895,7 +895,7 @@ static struct omap_hwmod omap54xx_mcpdm_hwmod = {
         * current exception.
         */
 
-       .flags          = HWMOD_EXT_OPT_MAIN_CLK,
+       .flags          = HWMOD_EXT_OPT_MAIN_CLK | HWMOD_SWSUP_SIDLE,
        .main_clk       = "pad_clks_ck",
        .prcm = {
                .omap4 = {
index f565f9944af2ee45b795b180391853ffa8810a12..7548db2bfb8a7e595d7672c5cfbba3868651d689 100644 (file)
@@ -21,7 +21,7 @@ struct mv_sata_platform_data;
 #define ORION_MBUS_DEVBUS_BOOT_ATTR   0x0f
 #define ORION_MBUS_DEVBUS_TARGET(cs)  0x01
 #define ORION_MBUS_DEVBUS_ATTR(cs)    (~(1 << cs))
-#define ORION_MBUS_SRAM_TARGET        0x00
+#define ORION_MBUS_SRAM_TARGET        0x09
 #define ORION_MBUS_SRAM_ATTR          0x00
 
 /*
index 0c93588fcb91b4a74791534e5db93be9c578e5ce..1ca37c72f12fb88934257db8356853b02c350f5f 100644 (file)
@@ -123,6 +123,11 @@ __v7m_setup:
        mov     pc, lr
 ENDPROC(__v7m_setup)
 
+       .align 2
+__v7m_setup_stack:
+       .space  4 * 8                           @ 8 registers
+__v7m_setup_stack_top:
+
        define_processor_functions v7m, dabort=nommu_early_abort, pabort=legacy_pabort, nommu=1
 
        .section ".rodata"
@@ -152,6 +157,3 @@ __v7m_proc_info:
        .long   nop_cache_fns           @ proc_info_list.cache
        .size   __v7m_proc_info, . - __v7m_proc_info
 
-__v7m_setup_stack:
-       .space  4 * 8                           @ 8 registers
-__v7m_setup_stack_top:
index 5f5b975887fc8424723d6566d687c82cf54328bc..b5608b1f9fbdf5da32bf354643c1c842a755df83 100644 (file)
@@ -70,6 +70,7 @@ static u32 errata;
 
 static struct omap_dma_global_context_registers {
        u32 dma_irqenable_l0;
+       u32 dma_irqenable_l1;
        u32 dma_ocp_sysconfig;
        u32 dma_gcr;
 } omap_dma_global_context;
@@ -1973,10 +1974,17 @@ static struct irqaction omap24xx_dma_irq;
 
 /*----------------------------------------------------------------------------*/
 
+/*
+ * Note that we are currently using only IRQENABLE_L0 and L1.
+ * As the DSP may be using IRQENABLE_L2 and L3, let's not
+ * touch those for now.
+ */
 void omap_dma_global_context_save(void)
 {
        omap_dma_global_context.dma_irqenable_l0 =
                p->dma_read(IRQENABLE_L0, 0);
+       omap_dma_global_context.dma_irqenable_l1 =
+               p->dma_read(IRQENABLE_L1, 0);
        omap_dma_global_context.dma_ocp_sysconfig =
                p->dma_read(OCP_SYSCONFIG, 0);
        omap_dma_global_context.dma_gcr = p->dma_read(GCR, 0);
@@ -1991,6 +1999,8 @@ void omap_dma_global_context_restore(void)
                OCP_SYSCONFIG, 0);
        p->dma_write(omap_dma_global_context.dma_irqenable_l0,
                IRQENABLE_L0, 0);
+       p->dma_write(omap_dma_global_context.dma_irqenable_l1,
+               IRQENABLE_L1, 0);
 
        if (IS_DMA_ERRATA(DMA_ROMCODE_BUG))
                p->dma_write(0x3 , IRQSTATUS_L0, 0);
index b96723e258a0857a0b148f3299947ba757a28c10..1e632430570b1ffc5d5358b55f0c8b4b43b80098 100644 (file)
@@ -339,6 +339,14 @@ static int __init xen_pm_init(void)
 }
 late_initcall(xen_pm_init);
 
+
+/* empty stubs */
+void xen_arch_pre_suspend(void) { }
+void xen_arch_post_suspend(int suspend_cancelled) { }
+void xen_timer_resume(void) { }
+void xen_arch_resume(void) { }
+
+
 /* In the hypervisor.S file. */
 EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op);
 EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op);
@@ -350,4 +358,5 @@ EXPORT_SYMBOL_GPL(HYPERVISOR_memory_op);
 EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op);
 EXPORT_SYMBOL_GPL(HYPERVISOR_vcpu_op);
 EXPORT_SYMBOL_GPL(HYPERVISOR_tmem_op);
+EXPORT_SYMBOL_GPL(HYPERVISOR_multicall);
 EXPORT_SYMBOL_GPL(privcmd_call);
index d1cf7b7c220013b4f553aae4481511fb7293131e..44e3a5f10c4cda982d1170a79c84303570e17bdc 100644 (file)
@@ -89,6 +89,7 @@ HYPERCALL2(memory_op);
 HYPERCALL2(physdev_op);
 HYPERCALL3(vcpu_op);
 HYPERCALL1(tmem_op);
+HYPERCALL2(multicall);
 
 ENTRY(privcmd_call)
        stmdb sp!, {r4}
index e94f9458aa6faa3630d5d2b7cebf9e522b56901d..993bce527b8552d379c62b6082703b1438e80436 100644 (file)
@@ -138,6 +138,7 @@ static inline void *phys_to_virt(phys_addr_t x)
 #define __pa(x)                        __virt_to_phys((unsigned long)(x))
 #define __va(x)                        ((void *)__phys_to_virt((phys_addr_t)(x)))
 #define pfn_to_kaddr(pfn)      __va((pfn) << PAGE_SHIFT)
+#define virt_to_pfn(x)      __phys_to_pfn(__virt_to_phys(x))
 
 /*
  *  virt_to_page(k)    convert a _valid_ virtual address to struct page *
index 90c811f05a2e3279a8709211a770725141491dd7..7b1c67a0b485b6ca7fa55e661e898b1938f4de26 100644 (file)
@@ -266,7 +266,7 @@ static inline pmd_t pte_pmd(pte_t pte)
 
 #define pmd_page(pmd)           pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
 
-#define set_pmd_at(mm, addr, pmdp, pmd)        set_pmd(pmdp, pmd)
+#define set_pmd_at(mm, addr, pmdp, pmd)        set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd))
 
 static inline int has_transparent_hugepage(void)
 {
index 473e5dbf8f39a39e8eaa7a0740e54ee4d6bacb59..0f08dfd69ebc73ea99b7b7f6d68c4b2f320eb2d1 100644 (file)
@@ -97,11 +97,15 @@ static bool migrate_one_irq(struct irq_desc *desc)
        if (irqd_is_per_cpu(d) || !cpumask_test_cpu(smp_processor_id(), affinity))
                return false;
 
-       if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
-               affinity = cpu_online_mask;
+       if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids)
                ret = true;
-       }
 
+       /*
+        * when using forced irq_set_affinity we must ensure that the cpu
+        * being offlined is not present in the affinity mask, it may be
+        * selected as the target CPU otherwise
+        */
+       affinity = cpu_online_mask;
        c = irq_data_get_irq_chip(d);
        if (!c->irq_set_affinity)
                pr_debug("IRQ%u: unable to set affinity\n", d->irq);
index 5e9aec358306f0c13bdd0bb70758dde88be9e961..31eb959e9aa81d05f16269e3bb500a965cb7cd48 100644 (file)
@@ -51,7 +51,11 @@ int pmd_huge(pmd_t pmd)
 
 int pud_huge(pud_t pud)
 {
+#ifndef __PAGETABLE_PMD_FOLDED
        return !(pud_val(pud) & PUD_TABLE_BIT);
+#else
+       return 0;
+#endif
 }
 
 int pmd_huge_support(void)
index 531342ec4bcf4d4769843a1176003d2c4c8549d9..8bbe9401f4f011d3239adcd2d6f5251d5fe37ff0 100644 (file)
@@ -80,6 +80,7 @@ HYPERCALL2(memory_op);
 HYPERCALL2(physdev_op);
 HYPERCALL3(vcpu_op);
 HYPERCALL1(tmem_op);
+HYPERCALL2(multicall);
 
 ENTRY(privcmd_call)
        mov x16, x0
index ae763d8bf55acff94a8c611893e2a103f3156f33..fb13dc5e8f8c7c34079664761f6fab1bf802a1c7 100644 (file)
@@ -11,7 +11,7 @@
 
 
 
-#define NR_syscalls                    314 /* length of syscall table */
+#define NR_syscalls                    315 /* length of syscall table */
 
 /*
  * The following defines stop scripts/checksyscalls.sh from complaining about
index 715e85f858de5ea34e7f581b38bc5d9a60ec1304..7de0a2d65da42a09b6d8b34f75f175c326b329e9 100644 (file)
 #define __NR_finit_module              1335
 #define __NR_sched_setattr             1336
 #define __NR_sched_getattr             1337
+#define __NR_renameat2                 1338
 
 #endif /* _UAPI_ASM_IA64_UNISTD_H */
index fa8d61a312a7ee818a300522d9f029c9534d78f6..ba3d03503e84fde7f714fda777acf254356b78e8 100644 (file)
@@ -1775,6 +1775,7 @@ sys_call_table:
        data8 sys_finit_module                  // 1335
        data8 sys_sched_setattr
        data8 sys_sched_getattr
+       data8 sys_renameat2
 
        .org sys_call_table + 8*NR_syscalls     // guard against failures to increase NR_syscalls
 #endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
index 229682721240a8a4193d3308335b611660722e3a..64776d7ac199ed74f524716196c820f2dab3de42 100644 (file)
@@ -12,12 +12,17 @@ config BOOTPARAM_STRING
 
 config EARLY_PRINTK
        bool "Early printk"
-       depends on MVME16x || MAC
+       depends on !(SUN3 || M68360 || M68000 || COLDFIRE)
        help
           Write kernel log output directly to a serial port.
+          Where implemented, output goes to the framebuffer as well.
+          PROM console functionality on Sun 3x is not affected by this option.
+
+          Pass "earlyprintk" on the kernel command line to get a
+          boot console.
 
           This is useful for kernel debugging when your machine crashes very
-          early before the console code is initialized.
+          early, i.e. before the normal console driver is loaded.
           You should normally say N here, unless you want to debug such a crash.
 
 if !MMU
index 2559eefc6aff9c09a6dc703af3f7ec1f014067f1..90a60d758f8b95f9ce637fbcd045723f0c482a44 100644 (file)
@@ -51,7 +51,7 @@ void __init amiga_init_sound(void)
 
        snd_data = amiga_chip_alloc_res(sizeof(sine_data), &beep_res);
        if (!snd_data) {
-               printk (KERN_CRIT "amiga init_sound: failed to allocate chipmem\n");
+               pr_crit("amiga init_sound: failed to allocate chipmem\n");
                return;
        }
        memcpy (snd_data, sine_data, sizeof(sine_data));
index 9625b71322275ea942da3bc1b3a6616e205bdc7a..01693df7f2f6ae261416083266991b91669f7aa9 100644 (file)
@@ -183,7 +183,7 @@ int __init amiga_parse_bootinfo(const struct bi_record *record)
                        dev->boardaddr = be32_to_cpu(cd->cd_BoardAddr);
                        dev->boardsize = be32_to_cpu(cd->cd_BoardSize);
                } else
-                       printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
+                       pr_warn("amiga_parse_bootinfo: too many AutoConfig devices\n");
 #endif /* CONFIG_ZORRO */
                break;
 
@@ -209,9 +209,9 @@ static void __init amiga_identify(void)
 
        memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
 
-       printk("Amiga hardware found: ");
+       pr_info("Amiga hardware found: ");
        if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) {
-               printk("[%s] ", amiga_models[amiga_model-AMI_500]);
+               pr_cont("[%s] ", amiga_models[amiga_model-AMI_500]);
                strcat(amiga_model_name, amiga_models[amiga_model-AMI_500]);
        }
 
@@ -322,7 +322,7 @@ static void __init amiga_identify(void)
 
 #define AMIGAHW_ANNOUNCE(name, str)            \
        if (AMIGAHW_PRESENT(name))              \
-               printk(str)
+               pr_cont(str)
 
        AMIGAHW_ANNOUNCE(AMI_VIDEO, "VIDEO ");
        AMIGAHW_ANNOUNCE(AMI_BLITTER, "BLITTER ");
@@ -354,8 +354,8 @@ static void __init amiga_identify(void)
        AMIGAHW_ANNOUNCE(MAGIC_REKICK, "MAGIC_REKICK ");
        AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA ");
        if (AMIGAHW_PRESENT(ZORRO))
-               printk("ZORRO%s ", AMIGAHW_PRESENT(ZORRO3) ? "3" : "");
-       printk("\n");
+               pr_cont("ZORRO%s ", AMIGAHW_PRESENT(ZORRO3) ? "3" : "");
+       pr_cont("\n");
 
 #undef AMIGAHW_ANNOUNCE
 }
@@ -424,7 +424,7 @@ void __init config_amiga(void)
                        if (m68k_memory[i].addr < 16*1024*1024) {
                                if (i == 0) {
                                        /* don't cut off the branch we're sitting on */
-                                       printk("Warning: kernel runs in Zorro II memory\n");
+                                       pr_warn("Warning: kernel runs in Zorro II memory\n");
                                        continue;
                                }
                                disabled_z2mem += m68k_memory[i].size;
@@ -435,8 +435,8 @@ void __init config_amiga(void)
                        }
                }
                if (disabled_z2mem)
-               printk("%dK of Zorro II memory will not be used as system memory\n",
-               disabled_z2mem>>10);
+                       pr_info("%dK of Zorro II memory will not be used as system memory\n",
+                               disabled_z2mem>>10);
        }
 
        /* request all RAM */
@@ -475,7 +475,7 @@ static void __init amiga_sched_init(irq_handler_t timer_routine)
        jiffy_ticks = DIV_ROUND_CLOSEST(amiga_eclock, HZ);
 
        if (request_resource(&mb_resources._ciab, &sched_res))
-               printk("Cannot allocate ciab.ta{lo,hi}\n");
+               pr_warn("Cannot allocate ciab.ta{lo,hi}\n");
        ciab.cra &= 0xC0;   /* turn off timer A, continuous mode, from Eclk */
        ciab.talo = jiffy_ticks % 256;
        ciab.tahi = jiffy_ticks / 256;
index 9268c0f96376b30eee39caba6d023d3fd0488cab..6e62d66c396eecde7acaf50c5241011fbaa0983a 100644 (file)
@@ -65,8 +65,8 @@ int __init apollo_parse_bootinfo(const struct bi_record *record)
 
 static void __init dn_setup_model(void)
 {
-       printk("Apollo hardware found: ");
-       printk("[%s]\n", apollo_models[apollo_model - APOLLO_DN3000]);
+       pr_info("Apollo hardware found: [%s]\n",
+               apollo_models[apollo_model - APOLLO_DN3000]);
 
        switch(apollo_model) {
                case APOLLO_UNKNOWN:
@@ -197,8 +197,10 @@ void dn_sched_init(irq_handler_t timer_routine)
        *(volatile unsigned char *)(pica+1)&=(~8);
 
 #if 0
-       printk("*(0x10803) %02x\n",*(volatile unsigned char *)(apollo_timer + 0x3));
-       printk("*(0x10803) %02x\n",*(volatile unsigned char *)(apollo_timer + 0x3));
+       pr_info("*(0x10803) %02x\n",
+               *(volatile unsigned char *)(apollo_timer + 0x3));
+       pr_info("*(0x10803) %02x\n",
+               *(volatile unsigned char *)(apollo_timer + 0x3));
 #endif
 
        if (request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", timer_routine))
@@ -236,12 +238,10 @@ int dn_dummy_hwclk(int op, struct rtc_time *t) {
 
 }
 
-int dn_dummy_set_clock_mmss(unsigned long nowtime) {
-
-  printk("set_clock_mmss\n");
-
-  return 0;
-
+int dn_dummy_set_clock_mmss(unsigned long nowtime)
+{
+       pr_info("set_clock_mmss\n");
+       return 0;
 }
 
 void dn_dummy_reset(void) {
index 0810c8d56e599b3e282af8a16ee003dab90ce8f4..5f8cb5a234d934fdd1f0377dbb62cd8a21475b09 100644 (file)
@@ -47,6 +47,7 @@ static struct resource stram_pool = {
 
 static unsigned long pool_size = 1024*1024;
 
+static unsigned long stram_virt_offset;
 
 static int __init atari_stram_setup(char *arg)
 {
@@ -67,14 +68,12 @@ early_param("stram_pool", atari_stram_setup);
 void __init atari_stram_init(void)
 {
        int i;
-       void *stram_start;
 
        /*
         * determine whether kernel code resides in ST-RAM
         * (then ST-RAM is the first memory block at virtual 0x0)
         */
-       stram_start = phys_to_virt(0);
-       kernel_in_stram = (stram_start == 0);
+       kernel_in_stram = (m68k_memory[0].addr == 0);
 
        for (i = 0; i < m68k_num_memory; ++i) {
                if (m68k_memory[i].addr == 0) {
@@ -89,24 +88,62 @@ void __init atari_stram_init(void)
 
 /*
  * This function is called from setup_arch() to reserve the pages needed for
- * ST-RAM management.
+ * ST-RAM management, if the kernel resides in ST-RAM.
  */
 void __init atari_stram_reserve_pages(void *start_mem)
 {
-       /*
-        * always reserve first page of ST-RAM, the first 2 KiB are
-        * supervisor-only!
-        */
-       if (!kernel_in_stram)
-               reserve_bootmem(0, PAGE_SIZE, BOOTMEM_DEFAULT);
+       if (kernel_in_stram) {
+               pr_debug("atari_stram pool: kernel in ST-RAM, using alloc_bootmem!\n");
+               stram_pool.start = (resource_size_t)alloc_bootmem_low_pages(pool_size);
+               stram_pool.end = stram_pool.start + pool_size - 1;
+               request_resource(&iomem_resource, &stram_pool);
+               stram_virt_offset = 0;
+               pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n",
+                       pool_size, &stram_pool);
+               pr_debug("atari_stram pool: stram_virt_offset = %lx\n",
+                       stram_virt_offset);
+       }
+}
 
-       stram_pool.start = (resource_size_t)alloc_bootmem_low_pages(pool_size);
-       stram_pool.end = stram_pool.start + pool_size - 1;
-       request_resource(&iomem_resource, &stram_pool);
 
-       pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n",
-                pool_size, &stram_pool);
+/*
+ * This function is called as arch initcall to reserve the pages needed for
+ * ST-RAM management, if the kernel does not reside in ST-RAM.
+ */
+int __init atari_stram_map_pages(void)
+{
+       if (!kernel_in_stram) {
+               /*
+                * Skip page 0, as the fhe first 2 KiB are supervisor-only!
+                */
+               pr_debug("atari_stram pool: kernel not in ST-RAM, using ioremap!\n");
+               stram_pool.start = PAGE_SIZE;
+               stram_pool.end = stram_pool.start + pool_size - 1;
+               request_resource(&iomem_resource, &stram_pool);
+               stram_virt_offset = (unsigned long) ioremap(stram_pool.start,
+                               resource_size(&stram_pool)) - stram_pool.start;
+               pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n",
+                       pool_size, &stram_pool);
+               pr_debug("atari_stram pool: stram_virt_offset = %lx\n",
+                       stram_virt_offset);
+       }
+       return 0;
+}
+arch_initcall(atari_stram_map_pages);
+
+
+void *atari_stram_to_virt(unsigned long phys)
+{
+       return (void *)(phys + stram_virt_offset);
+}
+EXPORT_SYMBOL(atari_stram_to_virt);
+
+
+unsigned long atari_stram_to_phys(void *virt)
+{
+       return (unsigned long)(virt - stram_virt_offset);
 }
+EXPORT_SYMBOL(atari_stram_to_phys);
 
 
 void *atari_stram_alloc(unsigned long size, const char *owner)
@@ -134,14 +171,14 @@ void *atari_stram_alloc(unsigned long size, const char *owner)
        }
 
        pr_debug("atari_stram_alloc: returning %pR\n", res);
-       return (void *)res->start;
+       return atari_stram_to_virt(res->start);
 }
 EXPORT_SYMBOL(atari_stram_alloc);
 
 
 void atari_stram_free(void *addr)
 {
-       unsigned long start = (unsigned long)addr;
+       unsigned long start = atari_stram_to_phys(addr);
        struct resource *res;
        unsigned long size;
 
index 96da4963d14b21ef0b5daa023b4d16425eaebeaf..d7eac833a94f6eeb2b5a03cf5b9937840bbb29b7 100644 (file)
@@ -159,6 +159,7 @@ CONFIG_IP_SET_BITMAP_IP=m
 CONFIG_IP_SET_BITMAP_IPMAC=m
 CONFIG_IP_SET_BITMAP_PORT=m
 CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
 CONFIG_IP_SET_HASH_IPPORT=m
 CONFIG_IP_SET_HASH_IPPORTIP=m
 CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -227,6 +228,7 @@ CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
 CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
 CONFIG_NETLINK_DIAG=m
 CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
@@ -279,6 +281,7 @@ CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
 CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
@@ -305,7 +308,6 @@ CONFIG_VETH=m
 CONFIG_A2065=y
 CONFIG_ARIADNE=y
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_CIRRUS is not set
 # CONFIG_NET_VENDOR_HP is not set
@@ -315,6 +317,7 @@ CONFIG_ARIADNE=y
 CONFIG_HYDRA=y
 CONFIG_APNE=y
 CONFIG_ZORRO8390=y
+# CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_SMSC is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
index 1b8739f50cbf77631d0eb5fb25d22941c7233aad..650ee75de6cd80762e17ae9453b0fda09f427fd1 100644 (file)
@@ -157,6 +157,7 @@ CONFIG_IP_SET_BITMAP_IP=m
 CONFIG_IP_SET_BITMAP_IPMAC=m
 CONFIG_IP_SET_BITMAP_PORT=m
 CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
 CONFIG_IP_SET_HASH_IPPORT=m
 CONFIG_IP_SET_HASH_IPPORTIP=m
 CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -225,6 +226,7 @@ CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
 CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
 CONFIG_NETLINK_DIAG=m
 CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
@@ -261,6 +263,7 @@ CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
 CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
@@ -284,12 +287,12 @@ CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
 # CONFIG_NET_VENDOR_VIA is not set
index 6ea4e91f0caabed1a806afbaab092744f23c0c98..3142e69342fa460186ddeb6c9daf172d234e3a34 100644 (file)
@@ -156,6 +156,7 @@ CONFIG_IP_SET_BITMAP_IP=m
 CONFIG_IP_SET_BITMAP_IPMAC=m
 CONFIG_IP_SET_BITMAP_PORT=m
 CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
 CONFIG_IP_SET_HASH_IPPORT=m
 CONFIG_IP_SET_HASH_IPPORTIP=m
 CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -224,6 +225,7 @@ CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
 CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
 CONFIG_NETLINK_DIAG=m
 CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
@@ -269,6 +271,7 @@ CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
 CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
@@ -293,11 +296,11 @@ CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 CONFIG_ATARILANCE=y
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
 # CONFIG_NET_VENDOR_VIA is not set
index e5a12739ff2d3535e8d9ed0dc22df8720eb4689e..0daa8a172f309f140d3bf40c5c3a6ec16edc4eb7 100644 (file)
@@ -155,6 +155,7 @@ CONFIG_IP_SET_BITMAP_IP=m
 CONFIG_IP_SET_BITMAP_IPMAC=m
 CONFIG_IP_SET_BITMAP_PORT=m
 CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
 CONFIG_IP_SET_HASH_IPPORT=m
 CONFIG_IP_SET_HASH_IPPORTIP=m
 CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -223,6 +224,7 @@ CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
 CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
 CONFIG_NETLINK_DIAG=m
 CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
@@ -260,6 +262,7 @@ CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
 CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
@@ -283,12 +286,12 @@ CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 CONFIG_BVME6000_NET=y
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
 # CONFIG_NET_VENDOR_VIA is not set
index 8936d7fb0f0f15a983dcd6d0262301a7447e10b9..88af78f7bad91b434dfa7674c13c3d2b143ca601 100644 (file)
@@ -157,6 +157,7 @@ CONFIG_IP_SET_BITMAP_IP=m
 CONFIG_IP_SET_BITMAP_IPMAC=m
 CONFIG_IP_SET_BITMAP_PORT=m
 CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
 CONFIG_IP_SET_HASH_IPPORT=m
 CONFIG_IP_SET_HASH_IPPORTIP=m
 CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -225,6 +226,7 @@ CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
 CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
 CONFIG_NETLINK_DIAG=m
 CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
@@ -261,6 +263,7 @@ CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
 CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
@@ -285,12 +288,12 @@ CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 CONFIG_HPLANCE=y
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
 # CONFIG_NET_VENDOR_VIA is not set
index be5342cca25b36180991f88a49d2bfe80f49ff2f..66f915574a85077e0ddf007488dd5a965b857d29 100644 (file)
@@ -156,6 +156,7 @@ CONFIG_IP_SET_BITMAP_IP=m
 CONFIG_IP_SET_BITMAP_IPMAC=m
 CONFIG_IP_SET_BITMAP_PORT=m
 CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
 CONFIG_IP_SET_HASH_IPPORT=m
 CONFIG_IP_SET_HASH_IPPORTIP=m
 CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -227,6 +228,7 @@ CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
 CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
 CONFIG_NETLINK_DIAG=m
 CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
@@ -270,6 +272,7 @@ CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
 CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
@@ -301,7 +304,6 @@ CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 CONFIG_MACMACE=y
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 CONFIG_MAC89x0=y
 # CONFIG_NET_VENDOR_INTEL is not set
@@ -309,6 +311,7 @@ CONFIG_MAC89x0=y
 # CONFIG_NET_VENDOR_MICREL is not set
 CONFIG_MACSONIC=y
 CONFIG_MAC8390=y
+# CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_SMSC is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
index f27194ade167d96fb949b1e2a42e7e74a75f6e79..5eaa49924fa6b85afb3ad99563a6ed46a08eaca0 100644 (file)
@@ -165,6 +165,7 @@ CONFIG_IP_SET_BITMAP_IP=m
 CONFIG_IP_SET_BITMAP_IPMAC=m
 CONFIG_IP_SET_BITMAP_PORT=m
 CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
 CONFIG_IP_SET_HASH_IPPORT=m
 CONFIG_IP_SET_HASH_IPPORTIP=m
 CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -236,6 +237,7 @@ CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
 CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
 CONFIG_NETLINK_DIAG=m
 CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
@@ -302,6 +304,7 @@ CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
 CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
@@ -340,7 +343,6 @@ CONFIG_MVME147_NET=y
 CONFIG_SUN3LANCE=y
 CONFIG_MACMACE=y
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 CONFIG_MAC89x0=y
 # CONFIG_NET_VENDOR_HP is not set
@@ -354,6 +356,7 @@ CONFIG_MAC8390=y
 CONFIG_NE2000=m
 CONFIG_APNE=y
 CONFIG_ZORRO8390=y
+# CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
 # CONFIG_NET_VENDOR_VIA is not set
index c3887603c1db4a49196af9a52c2dc85efdc641be..324d0b4d8351548f9a3f25510acc9649bc5aab7e 100644 (file)
@@ -154,6 +154,7 @@ CONFIG_IP_SET_BITMAP_IP=m
 CONFIG_IP_SET_BITMAP_IPMAC=m
 CONFIG_IP_SET_BITMAP_PORT=m
 CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
 CONFIG_IP_SET_HASH_IPPORT=m
 CONFIG_IP_SET_HASH_IPPORTIP=m
 CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -222,6 +223,7 @@ CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
 CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
 CONFIG_NETLINK_DIAG=m
 CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
@@ -259,6 +261,7 @@ CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
 CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
@@ -283,12 +286,12 @@ CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 CONFIG_MVME147_NET=y
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
 # CONFIG_NET_VENDOR_VIA is not set
index f7ff784d05aca2498040a3b47ea477c5793ac22d..f0cb4338952e3fcff9cd6a1c773e96ac523622a8 100644 (file)
@@ -155,6 +155,7 @@ CONFIG_IP_SET_BITMAP_IP=m
 CONFIG_IP_SET_BITMAP_IPMAC=m
 CONFIG_IP_SET_BITMAP_PORT=m
 CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
 CONFIG_IP_SET_HASH_IPPORT=m
 CONFIG_IP_SET_HASH_IPPORTIP=m
 CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -223,6 +224,7 @@ CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
 CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
 CONFIG_NETLINK_DIAG=m
 CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
@@ -260,6 +262,7 @@ CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
 CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
@@ -283,12 +286,12 @@ CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 CONFIG_MVME16x_NET=y
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
 # CONFIG_NET_VENDOR_VIA is not set
index f0c72ab037be1b268abcc720be5dda97fb128323..d6cf0880c46383ae76418ef896603e33a16f308f 100644 (file)
@@ -155,6 +155,7 @@ CONFIG_IP_SET_BITMAP_IP=m
 CONFIG_IP_SET_BITMAP_IPMAC=m
 CONFIG_IP_SET_BITMAP_PORT=m
 CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
 CONFIG_IP_SET_HASH_IPPORT=m
 CONFIG_IP_SET_HASH_IPPORTIP=m
 CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -223,6 +224,7 @@ CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
 CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
 CONFIG_NETLINK_DIAG=m
 CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
@@ -266,6 +268,7 @@ CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
 CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
@@ -291,7 +294,6 @@ CONFIG_VETH=m
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_NET_VENDOR_AMD is not set
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_CIRRUS is not set
 # CONFIG_NET_VENDOR_HP is not set
@@ -299,6 +301,7 @@ CONFIG_VETH=m
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 CONFIG_NE2000=m
+# CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_SMSC is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
index 7bca0f464521707451d41686040fac2dfc4b2070..f4e88d1c747281b80fd566aad89715ce6189bf8c 100644 (file)
@@ -152,6 +152,7 @@ CONFIG_IP_SET_BITMAP_IP=m
 CONFIG_IP_SET_BITMAP_IPMAC=m
 CONFIG_IP_SET_BITMAP_PORT=m
 CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
 CONFIG_IP_SET_HASH_IPPORT=m
 CONFIG_IP_SET_HASH_IPPORTIP=m
 CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -220,6 +221,7 @@ CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
 CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
 CONFIG_NETLINK_DIAG=m
 CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
@@ -257,6 +259,7 @@ CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
 CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
@@ -281,11 +284,11 @@ CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 CONFIG_SUN3LANCE=y
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
 CONFIG_SUN3_82586=y
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
 # CONFIG_NET_VENDOR_SUN is not set
index 317f3e1fec954285880d0268bce5af93cc23be1e..49f4032c1ad69c7905867aac75d83e25b77a1b26 100644 (file)
@@ -152,6 +152,7 @@ CONFIG_IP_SET_BITMAP_IP=m
 CONFIG_IP_SET_BITMAP_IPMAC=m
 CONFIG_IP_SET_BITMAP_PORT=m
 CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
 CONFIG_IP_SET_HASH_IPPORT=m
 CONFIG_IP_SET_HASH_IPPORTIP=m
 CONFIG_IP_SET_HASH_IPPORTNET=m
@@ -220,6 +221,7 @@ CONFIG_DNS_RESOLVER=y
 CONFIG_BATMAN_ADV=m
 CONFIG_BATMAN_ADV_DAT=y
 CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
 CONFIG_NETLINK_DIAG=m
 CONFIG_NET_MPLS_GSO=m
 # CONFIG_WIRELESS is not set
@@ -257,6 +259,7 @@ CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_THIN_PROVISIONING=m
 CONFIG_DM_CACHE=m
+CONFIG_DM_ERA=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_RAID=m
 CONFIG_DM_ZERO=m
@@ -281,12 +284,12 @@ CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_VETH=m
 CONFIG_SUN3LANCE=y
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
 # CONFIG_NET_VENDOR_VIA is not set
index 2e5a787ea11b8f987ef3994292c7d57832bfc266..a9befe65adc42b16e49ee318812eecb8d9b3a3f3 100644 (file)
@@ -87,7 +87,7 @@ int __init hp300_parse_bootinfo(const struct bi_record *record)
                /* serial port address: ignored here */
                break;
 
-        default:
+       default:
                unknown = 1;
        }
 
@@ -262,11 +262,12 @@ void __init config_hp300(void)
 #endif
        mach_max_dma_address = 0xffffffff;
 
-       if (hp300_model >= HP_330 && hp300_model <= HP_433S && hp300_model != HP_350) {
-               printk(KERN_INFO "Detected HP9000 model %s\n", hp300_models[hp300_model-HP_320]);
+       if (hp300_model >= HP_330 && hp300_model <= HP_433S &&
+           hp300_model != HP_350) {
+               pr_info("Detected HP9000 model %s\n",
+                       hp300_models[hp300_model-HP_320]);
                strcat(hp300_model_name, hp300_models[hp300_model-HP_320]);
-       }
-       else {
+       } else {
                panic("Unknown HP9000 Model");
        }
 #ifdef CONFIG_SERIAL_8250_CONSOLE
index 62e27598af91e5104c22aea3ac171dd9e10d4136..4e771c22d6a97f56beb71e59b59dc2f1df12d39d 100644 (file)
@@ -8,6 +8,8 @@
 /* public interface */
 void *atari_stram_alloc(unsigned long size, const char *owner);
 void atari_stram_free(void *);
+void *atari_stram_to_virt(unsigned long phys);
+unsigned long atari_stram_to_phys(void *);
 
 /* functions called internally by other parts of the kernel */
 void atari_stram_init(void);
index 9d38b73989eb597d677acd95ea53cf0ddb99b624..33afa56ad47aecd6620bc150eea042705cc85d3e 100644 (file)
@@ -4,7 +4,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define NR_syscalls            351
+#define NR_syscalls            352
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
index b932dd470041c2c5130dfcc44448c80033525259..9cd82fbc7817f716d589368bda3c1d274687a607 100644 (file)
 #define __NR_finit_module      348
 #define __NR_sched_setattr     349
 #define __NR_sched_getattr     350
+#define __NR_renameat2         351
 
 #endif /* _UAPI_ASM_M68K_UNISTD_H_ */
index 2d5d9be162732dae6ae603622e3572e1d0349523..e47778f8588dad0844c16bb1528c6b4d2fc8c7e9 100644 (file)
@@ -25,3 +25,5 @@ obj-$(CONFIG_HAS_DMA) += dma.o
 obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_BOOTINFO_PROC)    += bootinfo_proc.o
 
+obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
+
diff --git a/arch/m68k/kernel/early_printk.c b/arch/m68k/kernel/early_printk.c
new file mode 100644 (file)
index 0000000..ff9708d
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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) 2014 Finn Thain
+ */
+
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <asm/setup.h>
+
+extern void mvme16x_cons_write(struct console *co,
+                              const char *str, unsigned count);
+
+asmlinkage void __init debug_cons_nputs(const char *s, unsigned n);
+
+static void __ref debug_cons_write(struct console *c,
+                                  const char *s, unsigned n)
+{
+#if !(defined(CONFIG_SUN3)   || defined(CONFIG_M68360) || \
+      defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE))
+       if (MACH_IS_MVME16x)
+               mvme16x_cons_write(c, s, n);
+       else
+               debug_cons_nputs(s, n);
+#endif
+}
+
+static struct console early_console_instance = {
+       .name  = "debug",
+       .write = debug_cons_write,
+       .flags = CON_PRINTBUFFER | CON_BOOT,
+       .index = -1
+};
+
+static int __init setup_early_printk(char *buf)
+{
+       if (early_console || buf)
+               return 0;
+
+       early_console = &early_console_instance;
+       register_console(early_console);
+
+       return 0;
+}
+early_param("earlyprintk", setup_early_printk);
+
+/*
+ * debug_cons_nputs() defined in arch/m68k/kernel/head.S cannot be called
+ * after init sections are discarded (for platforms that use it).
+ */
+#if !(defined(CONFIG_SUN3)   || defined(CONFIG_M68360) || \
+      defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE))
+
+static int __init unregister_early_console(void)
+{
+       if (!early_console || MACH_IS_MVME16x)
+               return 0;
+
+       return unregister_console(early_console);
+}
+late_initcall(unregister_early_console);
+
+#endif
index 3ab329b8852173694bac06c2559841fed73d95ac..dbb118e1a4e091985724cf27fe4e1ce1e12248a2 100644 (file)
  * ------------
  *     The console is also able to be turned off.  The console in head.S
  * is specifically for debugging and can be very useful.  It is surrounded by
- * #ifdef CONSOLE/#endif clauses so it doesn't have to ship in known-good
+ * #ifdef #endif clauses so it doesn't have to ship in known-good
  * kernels.  It's basic algorithm is to determine the size of the screen
  * (in height/width and bit depth) and then use that information for
  * displaying an 8x8 font or an 8x16 (widthxheight).  I prefer the 8x8 for
  * CONFIG_xxx: These are the obvious machine configuration defines created
  * during configuration.  These are defined in autoconf.h.
  *
- * CONSOLE:    There is support for head.S console in this file.  This
- * console can talk to a Mac frame buffer, but could easily be extrapolated
- * to extend it to support other platforms.
+ * CONSOLE_DEBUG:  Only supports a Mac frame buffer but could easily be
+ * extended to support other platforms.
  *
  * TEST_MMU:   This is a test harness for running on any given machine but
  * getting an MMU dump for another class of machine.  The classes of machines
  * MMU_PRINT:  There is a routine built into head.S that can display the
  * MMU data structures.  It outputs its result through the serial_putc
  * interface.  So where ever that winds up driving data, that's where the
- * mmu struct will appear.  On the Macintosh that's typically the console.
+ * mmu struct will appear.
  *
  * SERIAL_DEBUG:       There are a series of putc() macro statements
  * scattered through out the code to give progress of status to the
  * USE_MFP:    Use the ST-MFP port (Modem1) for serial debug.
  *
  * Macintosh constants:
- * MAC_USE_SCC_A: Use SCC port A (modem) for serial debug and early console.
- * MAC_USE_SCC_B: Use SCC port B (printer) for serial debug and early console.
+ * MAC_USE_SCC_A: Use SCC port A (modem) for serial debug.
+ * MAC_USE_SCC_B: Use SCC port B (printer) for serial debug.
  */
 
 #include <linux/linkage.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/asm-offsets.h>
-
 #ifdef CONFIG_MAC
-
-#include <asm/machw.h>
-
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE
-#define CONSOLE
+#  include <asm/machw.h>
 #endif
 
 #ifdef CONFIG_EARLY_PRINTK
-#define SERIAL_DEBUG
-#else
-#undef SERIAL_DEBUG
+#  define SERIAL_DEBUG
+#  if defined(CONFIG_MAC) && defined(CONFIG_FONT_SUPPORT)
+#    define CONSOLE_DEBUG
+#  endif
 #endif
 
-#else /* !CONFIG_MAC */
-
-#define SERIAL_DEBUG
-
-#endif /* !CONFIG_MAC */
-
 #undef MMU_PRINT
 #undef MMU_NOCACHE_KERNEL
 #undef DEBUG
 
 .globl kernel_pg_dir
 .globl availmem
+.globl m68k_init_mapped_size
 .globl m68k_pgtable_cachemode
 .globl m68k_supervisor_cachemode
 #ifdef CONFIG_MVME16x
@@ -480,22 +470,21 @@ func_define       serial_putc,1
 func_define    console_putc,1
 
 func_define    console_init
-func_define    console_put_stats
 func_define    console_put_penguin
 func_define    console_plot_pixel,3
 func_define    console_scroll
 
 .macro putc    ch
-#if defined(CONSOLE) || defined(SERIAL_DEBUG)
+#if defined(CONSOLE_DEBUG) || defined(SERIAL_DEBUG)
        pea     \ch
 #endif
-#ifdef CONSOLE
+#ifdef CONSOLE_DEBUG
        func_call       console_putc
 #endif
 #ifdef SERIAL_DEBUG
        func_call       serial_putc
 #endif
-#if defined(CONSOLE) || defined(SERIAL_DEBUG)
+#if defined(CONSOLE_DEBUG) || defined(SERIAL_DEBUG)
        addql   #4,%sp
 #endif
 .endm
@@ -515,7 +504,7 @@ func_define putn,1
 .endm
 
 .macro puts            string
-#if defined(CONSOLE) || defined(SERIAL_DEBUG)
+#if defined(CONSOLE_DEBUG) || defined(SERIAL_DEBUG)
        __INITDATA
 .Lstr\@:
        .string "\string"
@@ -651,11 +640,9 @@ ENTRY(__start)
        lea     %pc@(L(mac_rowbytes)),%a1
        movel   %a0@,%a1@
 
-#ifdef SERIAL_DEBUG
        get_bi_record   BI_MAC_SCCBASE
        lea     %pc@(L(mac_sccbase)),%a1
        movel   %a0@,%a1@
-#endif
 
 L(test_notmac):
 #endif /* CONFIG_MAC */
@@ -885,13 +872,12 @@ L(nothp):
  */
 #ifdef CONFIG_MAC
        is_not_mac(L(nocon))
-#  ifdef CONSOLE
+#  ifdef CONSOLE_DEBUG
        console_init
 #    ifdef CONFIG_LOGO
        console_put_penguin
 #    endif /* CONFIG_LOGO */
-       console_put_stats
-#  endif /* CONSOLE */
+#  endif /* CONSOLE_DEBUG */
 L(nocon):
 #endif /* CONFIG_MAC */
 
@@ -922,10 +908,21 @@ L(nocon):
  *
  *     This block of code does what's necessary to map in the various kinds
  *     of machines for execution of Linux.
- *     First map the first 4 MB of kernel code & data
+ *     First map the first 4, 8, or 16 MB of kernel code & data
  */
 
-       mmu_map #PAGE_OFFSET,%pc@(L(phys_kernel_start)),#4*1024*1024,\
+       get_bi_record BI_MEMCHUNK
+       movel   %a0@(4),%d0
+       movel   #16*1024*1024,%d1
+       cmpl    %d0,%d1
+       jls     1f
+       lsrl    #1,%d1
+       cmpl    %d0,%d1
+       jls     1f
+       lsrl    #1,%d1
+1:
+       movel   %d1,m68k_init_mapped_size
+       mmu_map #PAGE_OFFSET,%pc@(L(phys_kernel_start)),%d1,\
                %pc@(m68k_supervisor_cachemode)
 
        putc    'C'
@@ -1396,15 +1393,13 @@ L(mmu_fixup_done):
        andl    L(mac_videobase),%d0
        addl    #VIDEOMEMBASE,%d0
        movel   %d0,L(mac_videobase)
-#if defined(CONSOLE)
+#ifdef CONSOLE_DEBUG
        movel   %pc@(L(phys_kernel_start)),%d0
        subl    #PAGE_OFFSET,%d0
        subl    %d0,L(console_font)
        subl    %d0,L(console_font_data)
 #endif
-#ifdef SERIAL_DEBUG
        orl     #0x50000000,L(mac_sccbase)
-#endif
 1:
 #endif
 
@@ -2734,7 +2729,12 @@ func_return      get_new_page
  */
 
 #ifdef CONFIG_MAC
+/* You may define either or both of these. */
+#define MAC_USE_SCC_A /* Modem port */
+#define MAC_USE_SCC_B /* Printer port */
 
+#if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B)
+/* Initialisation table for SCC with 3.6864 MHz PCLK */
 L(scc_initable_mac):
        .byte   4,0x44          /* x16, 1 stopbit, no parity */
        .byte   3,0xc0          /* receiver: 8 bpc */
@@ -2748,6 +2748,7 @@ L(scc_initable_mac):
        .byte   -1
        .even
 #endif
+#endif /* CONFIG_MAC */
 
 #ifdef CONFIG_ATARI
 /* #define USE_PRINTER */
@@ -2756,14 +2757,12 @@ L(scc_initable_mac):
 #define USE_MFP
 
 #if defined(USE_SCC_A) || defined(USE_SCC_B)
-#define USE_SCC
-/* Initialisation table for SCC */
-L(scc_initable):
-       .byte   9,12            /* Reset */
+/* Initialisation table for SCC with 7.9872 MHz PCLK */
+/* PCLK == 8.0539 gives baud == 9680.1 */
+L(scc_initable_atari):
        .byte   4,0x44          /* x16, 1 stopbit, no parity */
        .byte   3,0xc0          /* receiver: 8 bpc */
        .byte   5,0xe2          /* transmitter: 8 bpc, assert dtr/rts */
-       .byte   9,0             /* no interrupts */
        .byte   10,0            /* NRZ */
        .byte   11,0x50         /* use baud rate generator */
        .byte   12,24,13,0      /* 9600 baud */
@@ -2812,7 +2811,7 @@ LMFP_UDR     = 0xfffa2f
  */
 
 /*
- * Initialize serial port hardware for 9600/8/1
+ * Initialize serial port hardware
  */
 func_start     serial_init,%d0/%d1/%a0/%a1
        /*
@@ -2822,7 +2821,7 @@ func_start        serial_init,%d0/%d1/%a0/%a1
         *              d0 = boot info offset
         *      CONFIG_ATARI
         *              a0 = address of SCC
-        *              a1 = Liobase address/address of scc_initable
+        *              a1 = Liobase address/address of scc_initable_atari
         *              d0 = init data for serial port
         *      CONFIG_MAC
         *              a0 = address of SCC
@@ -2843,6 +2842,7 @@ func_start        serial_init,%d0/%d1/%a0/%a1
 |      movew   #61,CUSTOMBASE+C_SERPER-ZTWOBASE
 1:
 #endif
+
 #ifdef CONFIG_ATARI
        is_not_atari(4f)
        movel   %pc@(L(iobase)),%a1
@@ -2857,9 +2857,21 @@ func_start       serial_init,%d0/%d1/%a0/%a1
        moveb   %a1@(LPSG_READ),%d0
        bset    #5,%d0
        moveb   %d0,%a1@(LPSG_WRITE)
-#elif defined(USE_SCC)
+#elif defined(USE_SCC_A) || defined(USE_SCC_B)
        lea     %a1@(LSCC_CTRL),%a0
-       lea     %pc@(L(scc_initable)),%a1
+       /* Reset SCC register pointer */
+       moveb   %a0@,%d0
+       /* Reset SCC device: write register pointer then register value */
+       moveb   #9,%a0@
+       moveb   #0xc0,%a0@
+       /* Wait for 5 PCLK cycles, which is about 63 CPU cycles */
+       /* 5 / 7.9872 MHz = approx. 0.63 us = 63 / 100 MHz */
+       movel   #32,%d0
+2:
+       subq    #1,%d0
+       jne     2b
+       /* Initialize channel */
+       lea     %pc@(L(scc_initable_atari)),%a1
 2:     moveb   %a1@+,%d0
        jmi     3f
        moveb   %d0,%a0@
@@ -2877,21 +2889,14 @@ func_start      serial_init,%d0/%d1/%a0/%a1
        jra     L(serial_init_done)
 4:
 #endif
+
 #ifdef CONFIG_MAC
        is_not_mac(L(serial_init_not_mac))
-
-#ifdef SERIAL_DEBUG
-
-/* You may define either or both of these. */
-#define MAC_USE_SCC_A /* Modem port */
-#define MAC_USE_SCC_B /* Printer port */
-
+#if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B)
 #define mac_scc_cha_b_ctrl_offset      0x0
 #define mac_scc_cha_a_ctrl_offset      0x2
 #define mac_scc_cha_b_data_offset      0x4
 #define mac_scc_cha_a_data_offset      0x6
-
-#if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B)
        movel   %pc@(L(mac_sccbase)),%a0
        /* Reset SCC register pointer */
        moveb   %a0@(mac_scc_cha_a_ctrl_offset),%d0
@@ -2905,7 +2910,6 @@ func_start        serial_init,%d0/%d1/%a0/%a1
        subq    #1,%d0
        jne     5b
 #endif
-
 #ifdef MAC_USE_SCC_A
        /* Initialize channel A */
        lea     %pc@(L(scc_initable_mac)),%a1
@@ -2916,7 +2920,6 @@ func_start        serial_init,%d0/%d1/%a0/%a1
        jra     5b
 6:
 #endif /* MAC_USE_SCC_A */
-
 #ifdef MAC_USE_SCC_B
        /* Initialize channel B */
        lea     %pc@(L(scc_initable_mac)),%a1
@@ -2927,9 +2930,6 @@ func_start        serial_init,%d0/%d1/%a0/%a1
        jra     7b
 8:
 #endif /* MAC_USE_SCC_B */
-
-#endif /* SERIAL_DEBUG */
-
        jra     L(serial_init_done)
 L(serial_init_not_mac):
 #endif /* CONFIG_MAC */
@@ -2959,6 +2959,15 @@ L(serial_init_not_mac):
 2:
 #endif
 
+#ifdef CONFIG_MVME16x
+       is_not_mvme16x(L(serial_init_not_mvme16x))
+       moveb   #0x10,M167_PCSCCMICR
+       moveb   #0x10,M167_PCSCCTICR
+       moveb   #0x10,M167_PCSCCRICR
+       jra     L(serial_init_done)
+L(serial_init_not_mvme16x):
+#endif
+
 #ifdef CONFIG_APOLLO
 /* We count on the PROM initializing SIO1 */
 #endif
@@ -2998,27 +3007,19 @@ func_start      serial_putc,%d0/%d1/%a0/%a1
 
 #ifdef CONFIG_MAC
        is_not_mac(5f)
-
-#ifdef SERIAL_DEBUG
-
 #if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B)
        movel   %pc@(L(mac_sccbase)),%a1
 #endif
-
 #ifdef MAC_USE_SCC_A
 3:     btst    #2,%a1@(mac_scc_cha_a_ctrl_offset)
        jeq     3b
        moveb   %d0,%a1@(mac_scc_cha_a_data_offset)
 #endif /* MAC_USE_SCC_A */
-
 #ifdef MAC_USE_SCC_B
 4:     btst    #2,%a1@(mac_scc_cha_b_ctrl_offset)
        jeq     4b
        moveb   %d0,%a1@(mac_scc_cha_b_data_offset)
 #endif /* MAC_USE_SCC_B */
-
-#endif /* SERIAL_DEBUG */
-
        jra     L(serial_putc_done)
 5:
 #endif /* CONFIG_MAC */
@@ -3039,7 +3040,7 @@ func_start        serial_putc,%d0/%d1/%a0/%a1
        nop
        bset    #5,%d0
        moveb   %d0,%a1@(LPSG_WRITE)
-#elif defined(USE_SCC)
+#elif defined(USE_SCC_A) || defined(USE_SCC_B)
 3:     btst    #2,%a1@(LSCC_CTRL)
        jeq     3b
        moveb   %d0,%a1@(LSCC_DATA)
@@ -3195,7 +3196,7 @@ func_start        puts,%d0/%a0
        movel   ARG1,%a0
        jra     2f
 1:
-#ifdef CONSOLE
+#ifdef CONSOLE_DEBUG
        console_putc    %d0
 #endif
 #ifdef SERIAL_DEBUG
@@ -3224,7 +3225,7 @@ func_start        putn,%d0-%d2
        jls     2f
        addb    #'A'-('9'+1),%d2
 2:
-#ifdef CONSOLE
+#ifdef CONSOLE_DEBUG
        console_putc    %d2
 #endif
 #ifdef SERIAL_DEBUG
@@ -3234,21 +3235,19 @@ func_start      putn,%d0-%d2
 
 func_return    putn
 
-#ifdef CONFIG_MAC
+#ifdef CONFIG_EARLY_PRINTK
 /*
- *     mac_early_print
- *
  *     This routine takes its parameters on the stack.  It then
  *     turns around and calls the internal routines.  This routine
  *     is used by the boot console.
  *
  *     The calling parameters are:
- *             void mac_early_print(const char *str, unsigned length);
+ *             void debug_cons_nputs(const char *str, unsigned length)
  *
  *     This routine does NOT understand variable arguments only
  *     simple strings!
  */
-ENTRY(mac_early_print)
+ENTRY(debug_cons_nputs)
        moveml  %d0/%d1/%a0,%sp@-
        movew   %sr,%sp@-
        ori     #0x0700,%sr
@@ -3256,7 +3255,7 @@ ENTRY(mac_early_print)
        movel   %sp@(22),%d1            /* fetch parameter */
        jra     2f
 1:
-#ifdef CONSOLE
+#ifdef CONSOLE_DEBUG
        console_putc    %d0
 #endif
 #ifdef SERIAL_DEBUG
@@ -3270,7 +3269,7 @@ ENTRY(mac_early_print)
        movew   %sp@+,%sr
        moveml  %sp@+,%d0/%d1/%a0
        rts
-#endif /* CONFIG_MAC */
+#endif /* CONFIG_EARLY_PRINTK */
 
 #if defined(CONFIG_HP300) || defined(CONFIG_APOLLO)
 func_start     set_leds,%d0/%a0
@@ -3292,7 +3291,7 @@ func_start        set_leds,%d0/%a0
 func_return    set_leds
 #endif
 
-#ifdef CONSOLE
+#ifdef CONSOLE_DEBUG
 /*
  *     For continuity, see the data alignment
  *     to which this structure is tied.
@@ -3396,43 +3395,6 @@ L(console_clear_loop):
 1:
 func_return    console_init
 
-func_start     console_put_stats,%a0/%d7
-       /*
-        *      Some of the register usage that follows
-        *              a0 = pointer to boot_info
-        *              d7 = value of boot_info fields
-        */
-       puts    "\nMacLinux\n"
-
-#ifdef SERIAL_DEBUG
-       puts    "\n vidaddr:"
-       putn    %pc@(L(mac_videobase))          /* video addr. */
-
-       puts    "\n  _stext:"
-       lea     %pc@(_stext),%a0
-       putn    %a0
-
-       puts    "\nbootinfo:"
-       lea     %pc@(_end),%a0
-       putn    %a0
-
-       puts    "\n   cpuid:"
-       putn    %pc@(L(cputype))
-
-#  ifdef CONFIG_MAC
-       puts    "\n sccbase:"
-       putn    %pc@(L(mac_sccbase))
-#  endif
-#  ifdef MMU_PRINT
-       putc    '\n'
-       jbsr    mmu_print_machine_cpu_types
-#  endif
-#endif /* SERIAL_DEBUG */
-
-       putc    '\n'
-
-func_return    console_put_stats
-
 #ifdef CONFIG_LOGO
 func_start     console_put_penguin,%a0-%a1/%d0-%d7
        /*
@@ -3774,12 +3736,15 @@ L(white_16):
 
 L(console_plot_pixel_exit):
 func_return    console_plot_pixel
-#endif /* CONSOLE */
+#endif /* CONSOLE_DEBUG */
 
 
 __INITDATA
        .align  4
 
+m68k_init_mapped_size:
+       .long   0
+
 #if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA) || \
     defined(CONFIG_HP300) || defined(CONFIG_APOLLO)
 L(custom):
@@ -3787,7 +3752,7 @@ L(iobase):
        .long 0
 #endif
 
-#if defined(CONSOLE)
+#ifdef CONSOLE_DEBUG
 L(console_globals):
        .long   0               /* cursor column */
        .long   0               /* cursor row */
@@ -3798,7 +3763,7 @@ L(console_font):
        .long   0               /* pointer to console font (struct font_desc) */
 L(console_font_data):
        .long   0               /* pointer to console font data */
-#endif /* CONSOLE */
+#endif /* CONSOLE_DEBUG */
 
 #if defined(MMU_PRINT)
 L(mmu_print_data):
@@ -3838,7 +3803,9 @@ M167_CYIER = 0xfff45011
 M167_CYLICR = 0xfff45026
 M167_CYTEOIR = 0xfff45085
 M167_CYTDR = 0xfff450f8
+M167_PCSCCMICR = 0xfff4201d
 M167_PCSCCTICR = 0xfff4201e
+M167_PCSCCRICR = 0xfff4201f
 M167_PCTPIACKR = 0xfff42025
 #endif
 
@@ -3856,10 +3823,8 @@ L(mac_dimensions):
        .long   0
 L(mac_rowbytes):
        .long   0
-#ifdef SERIAL_DEBUG
 L(mac_sccbase):
        .long   0
-#endif
 #endif /* CONFIG_MAC */
 
 #if defined (CONFIG_APOLLO)
index b6223dc41d82870953be64b35fc409c4b5634070..501e102127899c6afaa893bd99d4d555f5bab8ec 100644 (file)
@@ -371,4 +371,5 @@ ENTRY(sys_call_table)
        .long sys_finit_module
        .long sys_sched_setattr
        .long sys_sched_getattr         /* 350 */
+       .long sys_renameat2
 
index 982c3fe73c4a45b45eeeff08e8d8446a47151c16..a471eab1a4dda8d65214df570da554b9be44e378 100644 (file)
@@ -71,31 +71,6 @@ static void mac_get_model(char *str);
 static void mac_identify(void);
 static void mac_report_hardware(void);
 
-#ifdef CONFIG_EARLY_PRINTK
-asmlinkage void __init mac_early_print(const char *s, unsigned n);
-
-static void __init mac_early_cons_write(struct console *con,
-                                 const char *s, unsigned n)
-{
-       mac_early_print(s, n);
-}
-
-static struct console __initdata mac_early_cons = {
-       .name  = "early",
-       .write = mac_early_cons_write,
-       .flags = CON_PRINTBUFFER | CON_BOOT,
-       .index = -1
-};
-
-int __init mac_unregister_early_cons(void)
-{
-       /* mac_early_print can't be used after init sections are discarded */
-       return unregister_console(&mac_early_cons);
-}
-
-late_initcall(mac_unregister_early_cons);
-#endif
-
 static void __init mac_sched_init(irq_handler_t vector)
 {
        via_init_clock(vector);
@@ -190,10 +165,6 @@ void __init config_mac(void)
        mach_beep = mac_mksound;
 #endif
 
-#ifdef CONFIG_EARLY_PRINTK
-       register_console(&mac_early_cons);
-#endif
-
        /*
         * Determine hardware present
         */
index 7d4024432163ffa534665582fcf522ed4e9ea51f..b958916e5eac96b250ef08e556983e059d7d0850 100644 (file)
@@ -45,7 +45,7 @@ EXPORT_SYMBOL(mm_cachebits);
 #endif
 
 /* size of memory already mapped in head.S */
-#define INIT_MAPPED_SIZE       (4UL<<20)
+extern __initdata unsigned long m68k_init_mapped_size;
 
 extern unsigned long availmem;
 
@@ -271,10 +271,12 @@ void __init paging_init(void)
         */
        addr = m68k_memory[0].addr;
        size = m68k_memory[0].size;
-       free_bootmem_node(NODE_DATA(0), availmem, min(INIT_MAPPED_SIZE, size) - (availmem - addr));
+       free_bootmem_node(NODE_DATA(0), availmem,
+                         min(m68k_init_mapped_size, size) - (availmem - addr));
        map_node(0);
-       if (size > INIT_MAPPED_SIZE)
-               free_bootmem_node(NODE_DATA(0), addr + INIT_MAPPED_SIZE, size - INIT_MAPPED_SIZE);
+       if (size > m68k_init_mapped_size)
+               free_bootmem_node(NODE_DATA(0), addr + m68k_init_mapped_size,
+                                 size - m68k_init_mapped_size);
 
        for (i = 1; i < m68k_num_memory; i++)
                map_node(i);
index eab7d342757ef6abdf01e13ff1a199209381c81d..a53803cc66cde8df435b70aac81b381c6bfe63a4 100644 (file)
@@ -213,7 +213,7 @@ static void __init mvme16x_init_IRQ (void)
 #define CySCRH         (0x22)
 #define CyTFTC         (0x80)
 
-static void cons_write(struct console *co, const char *str, unsigned count)
+void mvme16x_cons_write(struct console *co, const char *str, unsigned count)
 {
        volatile unsigned char *base_addr = (u_char *)CD2401_ADDR;
        volatile u_char sink;
@@ -268,20 +268,6 @@ static void cons_write(struct console *co, const char *str, unsigned count)
        base_addr[CyIER] = ier;
 }
 
-static struct console cons_info =
-{
-       .name   = "sercon",
-       .write  = cons_write,
-       .flags  = CON_PRINTBUFFER | CON_BOOT,
-       .index  = -1,
-};
-
-static void __init mvme16x_early_console(void)
-{
-       register_console(&cons_info);
-
-       printk(KERN_INFO "MVME16x: early console registered\n");
-}
 #endif
 
 void __init config_mvme16x(void)
@@ -336,16 +322,6 @@ void __init config_mvme16x(void)
     else
     {
        mvme16x_config = MVME16x_CONFIG_GOT_LP | MVME16x_CONFIG_GOT_CD2401;
-
-       /* Dont allow any interrupts from the CD2401 until the interrupt */
-       /* handlers are installed                                        */
-
-       pcc2chip[PccSCCMICR] = 0x10;
-       pcc2chip[PccSCCTICR] = 0x10;
-       pcc2chip[PccSCCRICR] = 0x10;
-#ifdef CONFIG_EARLY_PRINTK
-       mvme16x_early_console();
-#endif
     }
 }
 
index 5d6b4b407ddab29b677a7aa5328715127dfdad56..2d6f0de7732529212bf4a9256bb3720386e39e71 100644 (file)
@@ -15,6 +15,7 @@ static inline void wr_fence(void)
        volatile int *flushptr = (volatile int *) LINSYSEVENT_WR_FENCE;
        barrier();
        *flushptr = 0;
+       barrier();
 }
 
 #else /* CONFIG_METAG_META21 */
@@ -35,6 +36,7 @@ static inline void wr_fence(void)
        *flushptr = 0;
        *flushptr = 0;
        *flushptr = 0;
+       barrier();
 }
 
 #endif /* !CONFIG_METAG_META21 */
@@ -68,6 +70,7 @@ static inline void fence(void)
        volatile int *flushptr = (volatile int *) LINSYSEVENT_WR_ATOMIC_UNLOCK;
        barrier();
        *flushptr = 0;
+       barrier();
 }
 #define smp_mb()        fence()
 #define smp_rmb()       fence()
index f16477d1f571cb134a29e3afd13c480401f340ea..a8a37477c66e22a8e3c29ba2402ff6559a35bf27 100644 (file)
@@ -22,6 +22,8 @@
 /* Add an extra page of padding at the top of the stack for the guard page. */
 #define STACK_TOP      (TASK_SIZE - PAGE_SIZE)
 #define STACK_TOP_MAX  STACK_TOP
+/* Maximum virtual space for stack */
+#define STACK_SIZE_MAX (CONFIG_MAX_STACK_SIZE_MB*1024*1024)
 
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
index 84e09feb4d546fef7004746a8d5550bddb3f8d58..ab78be2b6eb0503f939cc85409d532a3b037b491 100644 (file)
@@ -4,11 +4,11 @@ include include/uapi/asm-generic/Kbuild.asm
 header-y += byteorder.h
 header-y += ech.h
 header-y += ptrace.h
-header-y += resource.h
 header-y += sigcontext.h
 header-y += siginfo.h
 header-y += swab.h
 header-y += unistd.h
 
 generic-y += mman.h
+generic-y += resource.h
 generic-y += setup.h
diff --git a/arch/metag/include/uapi/asm/resource.h b/arch/metag/include/uapi/asm/resource.h
deleted file mode 100644 (file)
index 526d23c..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _UAPI_METAG_RESOURCE_H
-#define _UAPI_METAG_RESOURCE_H
-
-#define _STK_LIM_MAX    (1 << 28)
-#include <asm-generic/resource.h>
-
-#endif /* _UAPI_METAG_RESOURCE_H */
index 1a5b4032cb662b4db660acebba0cacb7752a66f6..60a359cfa328f5e4a6cc96f1a90ec20a184447f9 100644 (file)
@@ -151,7 +151,7 @@ cflags-$(CONFIG_CPU_NEVADA) += $(call cc-option,-march=rm5200,-march=r5000) \
                        -Wa,--trap
 cflags-$(CONFIG_CPU_RM7000)    += $(call cc-option,-march=rm7000,-march=r5000) \
                        -Wa,--trap
-cflags-$(CONFIG_CPU_SB1)       += $(call cc-option,-march=sb1,-march=r5000) \
+cflags-$(CONFIG_CPU_SB1)       += $(call cc-option,-march=sb1 -mno-mdmx -mno-mips3d,-march=r5000) \
                        -Wa,--trap
 cflags-$(CONFIG_CPU_R8000)     += -march=r8000 -Wa,--trap
 cflags-$(CONFIG_CPU_R10000)    += $(call cc-option,-march=r10000,-march=r8000) \
index 5abf4e894216ac4b683772f6b187e4e9337eb2d5..2a66e908f6a9d9a276cad042ac793f692630255e 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
+#include <asm/cpu-type.h>
 #include <asm/irq_regs.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
index f434b759e3b9aaa0f6eb9ab07f85fb783de4a6ad..ec606363b80677fd464b92c13d5a905871b21466 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/types.h>
 
 #include <asm/addrspace.h>
+#include <asm/cpu-type.h>
 #include <asm/irq_regs.h>
 #include <asm/ptrace.h>
 #include <asm/traps.h>
index 064ae7a76bdc204c28e0c8e92ccd63400fbbf403..ae73e42ac20b163331a77439a75270320a77dfa8 100644 (file)
@@ -6,4 +6,3 @@
 lib-y                  += init.o memory.o cmdline.o identify.o console.o
 
 lib-$(CONFIG_32BIT)    += locore.o
-lib-$(CONFIG_64BIT)    += call_o32.o
diff --git a/arch/mips/dec/prom/call_o32.S b/arch/mips/dec/prom/call_o32.S
deleted file mode 100644 (file)
index 8c84981..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *     O32 interface for the 64 (or N32) ABI.
- *
- *     Copyright (C) 2002  Maciej W. Rozycki
- *
- *     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.
- */
-
-#include <asm/asm.h>
-#include <asm/regdef.h>
-
-/* Maximum number of arguments supported.  Must be even!  */
-#define O32_ARGC       32
-/* Number of static registers we save.  */
-#define O32_STATC      11
-/* Frame size for both of the above.  */
-#define O32_FRAMESZ    (4 * O32_ARGC + SZREG * O32_STATC)
-
-               .text
-
-/*
- * O32 function call dispatcher, for interfacing 32-bit ROM routines.
- *
- * The standard 64 (N32) calling sequence is supported, with a0
- * holding a function pointer, a1-a7 -- its first seven arguments
- * and the stack -- remaining ones (up to O32_ARGC, including a1-a7).
- * Static registers, gp and fp are preserved, v0 holds a result.
- * This code relies on the called o32 function for sp and ra
- * restoration and thus both this dispatcher and the current stack
- * have to be placed in a KSEGx (or KUSEG) address space.  Any
- * pointers passed have to point to addresses within one of these
- * spaces as well.
- */
-NESTED(call_o32, O32_FRAMESZ, ra)
-               REG_SUBU        sp,O32_FRAMESZ
-
-               REG_S           ra,O32_FRAMESZ-1*SZREG(sp)
-               REG_S           fp,O32_FRAMESZ-2*SZREG(sp)
-               REG_S           gp,O32_FRAMESZ-3*SZREG(sp)
-               REG_S           s7,O32_FRAMESZ-4*SZREG(sp)
-               REG_S           s6,O32_FRAMESZ-5*SZREG(sp)
-               REG_S           s5,O32_FRAMESZ-6*SZREG(sp)
-               REG_S           s4,O32_FRAMESZ-7*SZREG(sp)
-               REG_S           s3,O32_FRAMESZ-8*SZREG(sp)
-               REG_S           s2,O32_FRAMESZ-9*SZREG(sp)
-               REG_S           s1,O32_FRAMESZ-10*SZREG(sp)
-               REG_S           s0,O32_FRAMESZ-11*SZREG(sp)
-
-               move            jp,a0
-
-               sll             a0,a1,zero
-               sll             a1,a2,zero
-               sll             a2,a3,zero
-               sll             a3,a4,zero
-               sw              a5,0x10(sp)
-               sw              a6,0x14(sp)
-               sw              a7,0x18(sp)
-
-               PTR_LA          t0,O32_FRAMESZ(sp)
-               PTR_LA          t1,0x1c(sp)
-               li              t2,O32_ARGC-7
-1:
-               lw              t3,(t0)
-               REG_ADDU        t0,SZREG
-               sw              t3,(t1)
-               REG_SUBU        t2,1
-               REG_ADDU        t1,4
-               bnez            t2,1b
-
-               jalr            jp
-
-               REG_L           s0,O32_FRAMESZ-11*SZREG(sp)
-               REG_L           s1,O32_FRAMESZ-10*SZREG(sp)
-               REG_L           s2,O32_FRAMESZ-9*SZREG(sp)
-               REG_L           s3,O32_FRAMESZ-8*SZREG(sp)
-               REG_L           s4,O32_FRAMESZ-7*SZREG(sp)
-               REG_L           s5,O32_FRAMESZ-6*SZREG(sp)
-               REG_L           s6,O32_FRAMESZ-5*SZREG(sp)
-               REG_L           s7,O32_FRAMESZ-4*SZREG(sp)
-               REG_L           gp,O32_FRAMESZ-3*SZREG(sp)
-               REG_L           fp,O32_FRAMESZ-2*SZREG(sp)
-               REG_L           ra,O32_FRAMESZ-1*SZREG(sp)
-
-               REG_ADDU        sp,O32_FRAMESZ
-               jr              ra
-END(call_o32)
index b308b2a0613e210c1f7b068dfc6a7589f1ad2afb..4703fe4dbd9a7b6c192ce3e86d0c5bceada460f1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     O32 interface for the 64 (or N32) ABI.
  *
- *     Copyright (C) 2002  Maciej W. Rozycki
+ *     Copyright (C) 2002, 2014  Maciej W. Rozycki
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
 #include <asm/asm.h>
 #include <asm/regdef.h>
 
+/* O32 register size.  */
+#define O32_SZREG      4
 /* Maximum number of arguments supported.  Must be even!  */
 #define O32_ARGC       32
-/* Number of static registers we save. */
+/* Number of static registers we save.  */
 #define O32_STATC      11
-/* Frame size for static register  */
-#define O32_FRAMESZ    (SZREG * O32_STATC)
-/* Frame size on new stack */
-#define O32_FRAMESZ_NEW (SZREG + 4 * O32_ARGC)
+/* Argument area frame size.  */
+#define O32_ARGSZ      (O32_SZREG * O32_ARGC)
+/* Static register save area frame size.  */
+#define O32_STATSZ     (SZREG * O32_STATC)
+/* Stack pointer register save area frame size.  */
+#define O32_SPSZ       SZREG
+/* Combined area frame size.  */
+#define O32_FRAMESZ    (O32_ARGSZ + O32_SPSZ + O32_STATSZ)
+/* Switched stack frame size.  */
+#define O32_NFRAMESZ   (O32_ARGSZ + O32_SPSZ)
 
                .text
 
 /*
  * O32 function call dispatcher, for interfacing 32-bit ROM routines.
  *
- * The standard 64 (N32) calling sequence is supported, with a0
- * holding a function pointer, a1 a new stack pointer, a2-a7 -- its
- * first six arguments and the stack -- remaining ones (up to O32_ARGC,
- * including a2-a7). Static registers, gp and fp are preserved, v0 holds
- * a result. This code relies on the called o32 function for sp and ra
- * restoration and this dispatcher has to be placed in a KSEGx (or KUSEG)
- * address space.  Any pointers passed have to point to addresses within
- * one of these spaces as well.
+ * The standard 64 (N32) calling sequence is supported, with a0 holding
+ * a function pointer, a1 a pointer to the new stack to call the
+ * function with or 0 if no stack switching is requested, a2-a7 -- the
+ * function call's first six arguments, and the stack -- the remaining
+ * arguments (up to O32_ARGC, including a2-a7).  Static registers, gp
+ * and fp are preserved, v0 holds the result.  This code relies on the
+ * called o32 function for sp and ra restoration and this dispatcher has
+ * to be placed in a KSEGx (or KUSEG) address space.  Any pointers
+ * passed have to point to addresses within one of these spaces as well.
  */
 NESTED(call_o32, O32_FRAMESZ, ra)
                REG_SUBU        sp,O32_FRAMESZ
@@ -51,32 +60,36 @@ NESTED(call_o32, O32_FRAMESZ, ra)
                REG_S           s0,O32_FRAMESZ-11*SZREG(sp)
 
                move            jp,a0
-               REG_SUBU        s0,a1,O32_FRAMESZ_NEW
-               REG_S           sp,O32_FRAMESZ_NEW-1*SZREG(s0)
+
+               move            fp,sp
+               beqz            a1,0f
+               REG_SUBU        fp,a1,O32_NFRAMESZ
+0:
+               REG_S           sp,O32_NFRAMESZ-1*SZREG(fp)
 
                sll             a0,a2,zero
                sll             a1,a3,zero
                sll             a2,a4,zero
                sll             a3,a5,zero
-               sw              a6,0x10(s0)
-               sw              a7,0x14(s0)
+               sw              a6,4*O32_SZREG(fp)
+               sw              a7,5*O32_SZREG(fp)
 
                PTR_LA          t0,O32_FRAMESZ(sp)
-               PTR_LA          t1,0x18(s0)
+               PTR_LA          t1,6*O32_SZREG(fp)
                li              t2,O32_ARGC-6
 1:
                lw              t3,(t0)
                REG_ADDU        t0,SZREG
                sw              t3,(t1)
                REG_SUBU        t2,1
-               REG_ADDU        t1,4
+               REG_ADDU        t1,O32_SZREG
                bnez            t2,1b
 
-               move            sp,s0
+               move            sp,fp
 
                jalr            jp
 
-               REG_L           sp,O32_FRAMESZ_NEW-1*SZREG(sp)
+               REG_L           sp,O32_NFRAMESZ-1*SZREG(sp)
 
                REG_L           s0,O32_FRAMESZ-11*SZREG(sp)
                REG_L           s1,O32_FRAMESZ-10*SZREG(sp)
index 2c2cb182af4edd8673dc54c00c39aded85a6ed30..6aa264b9856ac99b71b88d54fae19cea27d782de 100644 (file)
@@ -40,7 +40,8 @@
 
 #ifdef CONFIG_64BIT
 
-static u8 o32_stk[16384];
+/* O32 stack has to be 8-byte aligned. */
+static u64 o32_stk[4096];
 #define O32_STK          &o32_stk[sizeof(o32_stk)]
 
 #define __PROM_O32(fun, arg) fun arg __asm__(#fun); \
index dc2135be2a3a4ed2c044870e3c8c8b24881535f6..ff2707ab3295f2b0cd3481168ee18360b0b0f15a 100644 (file)
@@ -39,14 +39,14 @@ struct cache_desc {
 #define MIPS_CACHE_PINDEX      0x00000020      /* Physically indexed cache */
 
 struct cpuinfo_mips {
-       unsigned int            udelay_val;
-       unsigned int            asid_cache;
+       unsigned long           asid_cache;
 
        /*
         * Capability and feature descriptor structure for MIPS CPU
         */
        unsigned long           options;
        unsigned long           ases;
+       unsigned int            udelay_val;
        unsigned int            processor_id;
        unsigned int            fpu_id;
        unsigned int            msa_id;
index c0ead63138453c04d3b20918fbcfb1e1c02c5c3c..b59a2103b61a3f64efd75b29f034e8208c155012 100644 (file)
@@ -113,31 +113,31 @@ extern int (*__pmax_close)(int);
 #define __DEC_PROM_O32(fun, arg) fun arg __asm__(#fun); \
                                 __asm__(#fun " = call_o32")
 
-int __DEC_PROM_O32(_rex_bootinit, (int (*)(void)));
-int __DEC_PROM_O32(_rex_bootread, (int (*)(void)));
-int __DEC_PROM_O32(_rex_getbitmap, (int (*)(memmap *), memmap *));
+int __DEC_PROM_O32(_rex_bootinit, (int (*)(void), void *));
+int __DEC_PROM_O32(_rex_bootread, (int (*)(void), void *));
+int __DEC_PROM_O32(_rex_getbitmap, (int (*)(memmap *), void *, memmap *));
 unsigned long *__DEC_PROM_O32(_rex_slot_address,
-                            (unsigned long *(*)(int), int));
-void *__DEC_PROM_O32(_rex_gettcinfo, (void *(*)(void)));
-int __DEC_PROM_O32(_rex_getsysid, (int (*)(void)));
-void __DEC_PROM_O32(_rex_clear_cache, (void (*)(void)));
-
-int __DEC_PROM_O32(_prom_getchar, (int (*)(void)));
-char *__DEC_PROM_O32(_prom_getenv, (char *(*)(char *), char *));
-int __DEC_PROM_O32(_prom_printf, (int (*)(char *, ...), char *, ...));
-
-
-#define rex_bootinit()         _rex_bootinit(__rex_bootinit)
-#define rex_bootread()         _rex_bootread(__rex_bootread)
-#define rex_getbitmap(x)       _rex_getbitmap(__rex_getbitmap, x)
-#define rex_slot_address(x)    _rex_slot_address(__rex_slot_address, x)
-#define rex_gettcinfo()                _rex_gettcinfo(__rex_gettcinfo)
-#define rex_getsysid()         _rex_getsysid(__rex_getsysid)
-#define rex_clear_cache()      _rex_clear_cache(__rex_clear_cache)
-
-#define prom_getchar()         _prom_getchar(__prom_getchar)
-#define prom_getenv(x)         _prom_getenv(__prom_getenv, x)
-#define prom_printf(x...)      _prom_printf(__prom_printf, x)
+                            (unsigned long *(*)(int), void *, int));
+void *__DEC_PROM_O32(_rex_gettcinfo, (void *(*)(void), void *));
+int __DEC_PROM_O32(_rex_getsysid, (int (*)(void), void *));
+void __DEC_PROM_O32(_rex_clear_cache, (void (*)(void), void *));
+
+int __DEC_PROM_O32(_prom_getchar, (int (*)(void), void *));
+char *__DEC_PROM_O32(_prom_getenv, (char *(*)(char *), void *, char *));
+int __DEC_PROM_O32(_prom_printf, (int (*)(char *, ...), void *, char *, ...));
+
+
+#define rex_bootinit()         _rex_bootinit(__rex_bootinit, NULL)
+#define rex_bootread()         _rex_bootread(__rex_bootread, NULL)
+#define rex_getbitmap(x)       _rex_getbitmap(__rex_getbitmap, NULL, x)
+#define rex_slot_address(x)    _rex_slot_address(__rex_slot_address, NULL, x)
+#define rex_gettcinfo()                _rex_gettcinfo(__rex_gettcinfo, NULL)
+#define rex_getsysid()         _rex_getsysid(__rex_getsysid, NULL)
+#define rex_clear_cache()      _rex_clear_cache(__rex_clear_cache, NULL)
+
+#define prom_getchar()         _prom_getchar(__prom_getchar, NULL)
+#define prom_getenv(x)         _prom_getenv(__prom_getenv, NULL, x)
+#define prom_printf(x...)      _prom_printf(__prom_printf, NULL, x)
 
 #else /* !CONFIG_64BIT */
 
diff --git a/arch/mips/include/asm/rm9k-ocd.h b/arch/mips/include/asm/rm9k-ocd.h
deleted file mode 100644 (file)
index b0b80d9..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *  Copyright (C) 2004 by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslerweb.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
- */
-
-#if !defined(_ASM_RM9K_OCD_H)
-#define _ASM_RM9K_OCD_H
-
-#include <linux/types.h>
-#include <linux/spinlock.h>
-#include <asm/io.h>
-
-extern volatile void __iomem * const ocd_base;
-extern volatile void __iomem * const titan_base;
-
-#define ocd_addr(__x__)                (ocd_base + (__x__))
-#define titan_addr(__x__)      (titan_base + (__x__))
-#define scram_addr(__x__)      (scram_base + (__x__))
-
-/* OCD register access */
-#define ocd_readl(__offs__) __raw_readl(ocd_addr(__offs__))
-#define ocd_readw(__offs__) __raw_readw(ocd_addr(__offs__))
-#define ocd_readb(__offs__) __raw_readb(ocd_addr(__offs__))
-#define ocd_writel(__val__, __offs__) \
-       __raw_writel((__val__), ocd_addr(__offs__))
-#define ocd_writew(__val__, __offs__) \
-       __raw_writew((__val__), ocd_addr(__offs__))
-#define ocd_writeb(__val__, __offs__) \
-       __raw_writeb((__val__), ocd_addr(__offs__))
-
-/* TITAN register access - 32 bit-wide only */
-#define titan_readl(__offs__) __raw_readl(titan_addr(__offs__))
-#define titan_writel(__val__, __offs__) \
-       __raw_writel((__val__), titan_addr(__offs__))
-
-/* Protect access to shared TITAN registers */
-extern spinlock_t titan_lock;
-extern int titan_irqflags;
-#define lock_titan_regs() spin_lock_irqsave(&titan_lock, titan_irqflags)
-#define unlock_titan_regs() spin_unlock_irqrestore(&titan_lock, titan_irqflags)
-
-#endif /* !defined(_ASM_RM9K_OCD_H) */
index c6e9cd2bca8dbf7de5512c9be8de0f2b92db7bd4..17960fe7a8ce4ef21b7a94cca10c7b5af61cec17 100644 (file)
@@ -133,6 +133,8 @@ static inline int syscall_get_arch(void)
 #ifdef CONFIG_64BIT
        if (!test_thread_flag(TIF_32BIT_REGS))
                arch |= __AUDIT_ARCH_64BIT;
+       if (test_thread_flag(TIF_32BIT_ADDR))
+               arch |= __AUDIT_ARCH_CONVENTION_MIPS64_N32;
 #endif
 #if defined(__LITTLE_ENDIAN)
        arch |=  __AUDIT_ARCH_LE;
index df6e775f3fef524e8d049c24433eff06dade0fd7..3125797f2a88a6bc3e44cdc215d416d604e7070d 100644 (file)
@@ -484,13 +484,13 @@ enum MIPS6e_i8_func {
  * Damn ...  bitfields depend from byteorder :-(
  */
 #ifdef __MIPSEB__
-#define BITFIELD_FIELD(field, more)                                    \
+#define __BITFIELD_FIELD(field, more)                                  \
        field;                                                          \
        more
 
 #elif defined(__MIPSEL__)
 
-#define BITFIELD_FIELD(field, more)                                    \
+#define __BITFIELD_FIELD(field, more)                                  \
        more                                                            \
        field;
 
@@ -499,112 +499,112 @@ enum MIPS6e_i8_func {
 #endif
 
 struct j_format {
-       BITFIELD_FIELD(unsigned int opcode : 6, /* Jump format */
-       BITFIELD_FIELD(unsigned int target : 26,
+       __BITFIELD_FIELD(unsigned int opcode : 6, /* Jump format */
+       __BITFIELD_FIELD(unsigned int target : 26,
        ;))
 };
 
 struct i_format {                      /* signed immediate format */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int rs : 5,
-       BITFIELD_FIELD(unsigned int rt : 5,
-       BITFIELD_FIELD(signed int simmediate : 16,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int rs : 5,
+       __BITFIELD_FIELD(unsigned int rt : 5,
+       __BITFIELD_FIELD(signed int simmediate : 16,
        ;))))
 };
 
 struct u_format {                      /* unsigned immediate format */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int rs : 5,
-       BITFIELD_FIELD(unsigned int rt : 5,
-       BITFIELD_FIELD(unsigned int uimmediate : 16,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int rs : 5,
+       __BITFIELD_FIELD(unsigned int rt : 5,
+       __BITFIELD_FIELD(unsigned int uimmediate : 16,
        ;))))
 };
 
 struct c_format {                      /* Cache (>= R6000) format */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int rs : 5,
-       BITFIELD_FIELD(unsigned int c_op : 3,
-       BITFIELD_FIELD(unsigned int cache : 2,
-       BITFIELD_FIELD(unsigned int simmediate : 16,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int rs : 5,
+       __BITFIELD_FIELD(unsigned int c_op : 3,
+       __BITFIELD_FIELD(unsigned int cache : 2,
+       __BITFIELD_FIELD(unsigned int simmediate : 16,
        ;)))))
 };
 
 struct r_format {                      /* Register format */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int rs : 5,
-       BITFIELD_FIELD(unsigned int rt : 5,
-       BITFIELD_FIELD(unsigned int rd : 5,
-       BITFIELD_FIELD(unsigned int re : 5,
-       BITFIELD_FIELD(unsigned int func : 6,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int rs : 5,
+       __BITFIELD_FIELD(unsigned int rt : 5,
+       __BITFIELD_FIELD(unsigned int rd : 5,
+       __BITFIELD_FIELD(unsigned int re : 5,
+       __BITFIELD_FIELD(unsigned int func : 6,
        ;))))))
 };
 
 struct p_format {              /* Performance counter format (R10000) */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int rs : 5,
-       BITFIELD_FIELD(unsigned int rt : 5,
-       BITFIELD_FIELD(unsigned int rd : 5,
-       BITFIELD_FIELD(unsigned int re : 5,
-       BITFIELD_FIELD(unsigned int func : 6,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int rs : 5,
+       __BITFIELD_FIELD(unsigned int rt : 5,
+       __BITFIELD_FIELD(unsigned int rd : 5,
+       __BITFIELD_FIELD(unsigned int re : 5,
+       __BITFIELD_FIELD(unsigned int func : 6,
        ;))))))
 };
 
 struct f_format {                      /* FPU register format */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int : 1,
-       BITFIELD_FIELD(unsigned int fmt : 4,
-       BITFIELD_FIELD(unsigned int rt : 5,
-       BITFIELD_FIELD(unsigned int rd : 5,
-       BITFIELD_FIELD(unsigned int re : 5,
-       BITFIELD_FIELD(unsigned int func : 6,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int : 1,
+       __BITFIELD_FIELD(unsigned int fmt : 4,
+       __BITFIELD_FIELD(unsigned int rt : 5,
+       __BITFIELD_FIELD(unsigned int rd : 5,
+       __BITFIELD_FIELD(unsigned int re : 5,
+       __BITFIELD_FIELD(unsigned int func : 6,
        ;)))))))
 };
 
 struct ma_format {             /* FPU multiply and add format (MIPS IV) */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int fr : 5,
-       BITFIELD_FIELD(unsigned int ft : 5,
-       BITFIELD_FIELD(unsigned int fs : 5,
-       BITFIELD_FIELD(unsigned int fd : 5,
-       BITFIELD_FIELD(unsigned int func : 4,
-       BITFIELD_FIELD(unsigned int fmt : 2,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int fr : 5,
+       __BITFIELD_FIELD(unsigned int ft : 5,
+       __BITFIELD_FIELD(unsigned int fs : 5,
+       __BITFIELD_FIELD(unsigned int fd : 5,
+       __BITFIELD_FIELD(unsigned int func : 4,
+       __BITFIELD_FIELD(unsigned int fmt : 2,
        ;)))))))
 };
 
 struct b_format {                      /* BREAK and SYSCALL */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int code : 20,
-       BITFIELD_FIELD(unsigned int func : 6,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int code : 20,
+       __BITFIELD_FIELD(unsigned int func : 6,
        ;)))
 };
 
 struct ps_format {                     /* MIPS-3D / paired single format */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int rs : 5,
-       BITFIELD_FIELD(unsigned int ft : 5,
-       BITFIELD_FIELD(unsigned int fs : 5,
-       BITFIELD_FIELD(unsigned int fd : 5,
-       BITFIELD_FIELD(unsigned int func : 6,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int rs : 5,
+       __BITFIELD_FIELD(unsigned int ft : 5,
+       __BITFIELD_FIELD(unsigned int fs : 5,
+       __BITFIELD_FIELD(unsigned int fd : 5,
+       __BITFIELD_FIELD(unsigned int func : 6,
        ;))))))
 };
 
 struct v_format {                              /* MDMX vector format */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int sel : 4,
-       BITFIELD_FIELD(unsigned int fmt : 1,
-       BITFIELD_FIELD(unsigned int vt : 5,
-       BITFIELD_FIELD(unsigned int vs : 5,
-       BITFIELD_FIELD(unsigned int vd : 5,
-       BITFIELD_FIELD(unsigned int func : 6,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int sel : 4,
+       __BITFIELD_FIELD(unsigned int fmt : 1,
+       __BITFIELD_FIELD(unsigned int vt : 5,
+       __BITFIELD_FIELD(unsigned int vs : 5,
+       __BITFIELD_FIELD(unsigned int vd : 5,
+       __BITFIELD_FIELD(unsigned int func : 6,
        ;)))))))
 };
 
 struct spec3_format {   /* SPEC3 */
-       BITFIELD_FIELD(unsigned int opcode:6,
-       BITFIELD_FIELD(unsigned int rs:5,
-       BITFIELD_FIELD(unsigned int rt:5,
-       BITFIELD_FIELD(signed int simmediate:9,
-       BITFIELD_FIELD(unsigned int func:7,
+       __BITFIELD_FIELD(unsigned int opcode:6,
+       __BITFIELD_FIELD(unsigned int rs:5,
+       __BITFIELD_FIELD(unsigned int rt:5,
+       __BITFIELD_FIELD(signed int simmediate:9,
+       __BITFIELD_FIELD(unsigned int func:7,
        ;)))))
 };
 
@@ -616,141 +616,141 @@ struct spec3_format {   /* SPEC3 */
  *     if it is MIPS32 instruction re-encoded for use in the microMIPS ASE.
  */
 struct fb_format {             /* FPU branch format (MIPS32) */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int bc : 5,
-       BITFIELD_FIELD(unsigned int cc : 3,
-       BITFIELD_FIELD(unsigned int flag : 2,
-       BITFIELD_FIELD(signed int simmediate : 16,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int bc : 5,
+       __BITFIELD_FIELD(unsigned int cc : 3,
+       __BITFIELD_FIELD(unsigned int flag : 2,
+       __BITFIELD_FIELD(signed int simmediate : 16,
        ;)))))
 };
 
 struct fp0_format {            /* FPU multiply and add format (MIPS32) */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int fmt : 5,
-       BITFIELD_FIELD(unsigned int ft : 5,
-       BITFIELD_FIELD(unsigned int fs : 5,
-       BITFIELD_FIELD(unsigned int fd : 5,
-       BITFIELD_FIELD(unsigned int func : 6,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int fmt : 5,
+       __BITFIELD_FIELD(unsigned int ft : 5,
+       __BITFIELD_FIELD(unsigned int fs : 5,
+       __BITFIELD_FIELD(unsigned int fd : 5,
+       __BITFIELD_FIELD(unsigned int func : 6,
        ;))))))
 };
 
 struct mm_fp0_format {         /* FPU multipy and add format (microMIPS) */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int ft : 5,
-       BITFIELD_FIELD(unsigned int fs : 5,
-       BITFIELD_FIELD(unsigned int fd : 5,
-       BITFIELD_FIELD(unsigned int fmt : 3,
-       BITFIELD_FIELD(unsigned int op : 2,
-       BITFIELD_FIELD(unsigned int func : 6,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int ft : 5,
+       __BITFIELD_FIELD(unsigned int fs : 5,
+       __BITFIELD_FIELD(unsigned int fd : 5,
+       __BITFIELD_FIELD(unsigned int fmt : 3,
+       __BITFIELD_FIELD(unsigned int op : 2,
+       __BITFIELD_FIELD(unsigned int func : 6,
        ;)))))))
 };
 
 struct fp1_format {            /* FPU mfc1 and cfc1 format (MIPS32) */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int op : 5,
-       BITFIELD_FIELD(unsigned int rt : 5,
-       BITFIELD_FIELD(unsigned int fs : 5,
-       BITFIELD_FIELD(unsigned int fd : 5,
-       BITFIELD_FIELD(unsigned int func : 6,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int op : 5,
+       __BITFIELD_FIELD(unsigned int rt : 5,
+       __BITFIELD_FIELD(unsigned int fs : 5,
+       __BITFIELD_FIELD(unsigned int fd : 5,
+       __BITFIELD_FIELD(unsigned int func : 6,
        ;))))))
 };
 
 struct mm_fp1_format {         /* FPU mfc1 and cfc1 format (microMIPS) */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int rt : 5,
-       BITFIELD_FIELD(unsigned int fs : 5,
-       BITFIELD_FIELD(unsigned int fmt : 2,
-       BITFIELD_FIELD(unsigned int op : 8,
-       BITFIELD_FIELD(unsigned int func : 6,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int rt : 5,
+       __BITFIELD_FIELD(unsigned int fs : 5,
+       __BITFIELD_FIELD(unsigned int fmt : 2,
+       __BITFIELD_FIELD(unsigned int op : 8,
+       __BITFIELD_FIELD(unsigned int func : 6,
        ;))))))
 };
 
 struct mm_fp2_format {         /* FPU movt and movf format (microMIPS) */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int fd : 5,
-       BITFIELD_FIELD(unsigned int fs : 5,
-       BITFIELD_FIELD(unsigned int cc : 3,
-       BITFIELD_FIELD(unsigned int zero : 2,
-       BITFIELD_FIELD(unsigned int fmt : 2,
-       BITFIELD_FIELD(unsigned int op : 3,
-       BITFIELD_FIELD(unsigned int func : 6,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int fd : 5,
+       __BITFIELD_FIELD(unsigned int fs : 5,
+       __BITFIELD_FIELD(unsigned int cc : 3,
+       __BITFIELD_FIELD(unsigned int zero : 2,
+       __BITFIELD_FIELD(unsigned int fmt : 2,
+       __BITFIELD_FIELD(unsigned int op : 3,
+       __BITFIELD_FIELD(unsigned int func : 6,
        ;))))))))
 };
 
 struct mm_fp3_format {         /* FPU abs and neg format (microMIPS) */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int rt : 5,
-       BITFIELD_FIELD(unsigned int fs : 5,
-       BITFIELD_FIELD(unsigned int fmt : 3,
-       BITFIELD_FIELD(unsigned int op : 7,
-       BITFIELD_FIELD(unsigned int func : 6,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int rt : 5,
+       __BITFIELD_FIELD(unsigned int fs : 5,
+       __BITFIELD_FIELD(unsigned int fmt : 3,
+       __BITFIELD_FIELD(unsigned int op : 7,
+       __BITFIELD_FIELD(unsigned int func : 6,
        ;))))))
 };
 
 struct mm_fp4_format {         /* FPU c.cond format (microMIPS) */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int rt : 5,
-       BITFIELD_FIELD(unsigned int fs : 5,
-       BITFIELD_FIELD(unsigned int cc : 3,
-       BITFIELD_FIELD(unsigned int fmt : 3,
-       BITFIELD_FIELD(unsigned int cond : 4,
-       BITFIELD_FIELD(unsigned int func : 6,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int rt : 5,
+       __BITFIELD_FIELD(unsigned int fs : 5,
+       __BITFIELD_FIELD(unsigned int cc : 3,
+       __BITFIELD_FIELD(unsigned int fmt : 3,
+       __BITFIELD_FIELD(unsigned int cond : 4,
+       __BITFIELD_FIELD(unsigned int func : 6,
        ;)))))))
 };
 
 struct mm_fp5_format {         /* FPU lwxc1 and swxc1 format (microMIPS) */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int index : 5,
-       BITFIELD_FIELD(unsigned int base : 5,
-       BITFIELD_FIELD(unsigned int fd : 5,
-       BITFIELD_FIELD(unsigned int op : 5,
-       BITFIELD_FIELD(unsigned int func : 6,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int index : 5,
+       __BITFIELD_FIELD(unsigned int base : 5,
+       __BITFIELD_FIELD(unsigned int fd : 5,
+       __BITFIELD_FIELD(unsigned int op : 5,
+       __BITFIELD_FIELD(unsigned int func : 6,
        ;))))))
 };
 
 struct fp6_format {            /* FPU madd and msub format (MIPS IV) */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int fr : 5,
-       BITFIELD_FIELD(unsigned int ft : 5,
-       BITFIELD_FIELD(unsigned int fs : 5,
-       BITFIELD_FIELD(unsigned int fd : 5,
-       BITFIELD_FIELD(unsigned int func : 6,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int fr : 5,
+       __BITFIELD_FIELD(unsigned int ft : 5,
+       __BITFIELD_FIELD(unsigned int fs : 5,
+       __BITFIELD_FIELD(unsigned int fd : 5,
+       __BITFIELD_FIELD(unsigned int func : 6,
        ;))))))
 };
 
 struct mm_fp6_format {         /* FPU madd and msub format (microMIPS) */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int ft : 5,
-       BITFIELD_FIELD(unsigned int fs : 5,
-       BITFIELD_FIELD(unsigned int fd : 5,
-       BITFIELD_FIELD(unsigned int fr : 5,
-       BITFIELD_FIELD(unsigned int func : 6,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int ft : 5,
+       __BITFIELD_FIELD(unsigned int fs : 5,
+       __BITFIELD_FIELD(unsigned int fd : 5,
+       __BITFIELD_FIELD(unsigned int fr : 5,
+       __BITFIELD_FIELD(unsigned int func : 6,
        ;))))))
 };
 
 struct mm_i_format {           /* Immediate format (microMIPS) */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int rt : 5,
-       BITFIELD_FIELD(unsigned int rs : 5,
-       BITFIELD_FIELD(signed int simmediate : 16,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int rt : 5,
+       __BITFIELD_FIELD(unsigned int rs : 5,
+       __BITFIELD_FIELD(signed int simmediate : 16,
        ;))))
 };
 
 struct mm_m_format {           /* Multi-word load/store format (microMIPS) */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int rd : 5,
-       BITFIELD_FIELD(unsigned int base : 5,
-       BITFIELD_FIELD(unsigned int func : 4,
-       BITFIELD_FIELD(signed int simmediate : 12,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int rd : 5,
+       __BITFIELD_FIELD(unsigned int base : 5,
+       __BITFIELD_FIELD(unsigned int func : 4,
+       __BITFIELD_FIELD(signed int simmediate : 12,
        ;)))))
 };
 
 struct mm_x_format {           /* Scaled indexed load format (microMIPS) */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int index : 5,
-       BITFIELD_FIELD(unsigned int base : 5,
-       BITFIELD_FIELD(unsigned int rd : 5,
-       BITFIELD_FIELD(unsigned int func : 11,
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int index : 5,
+       __BITFIELD_FIELD(unsigned int base : 5,
+       __BITFIELD_FIELD(unsigned int rd : 5,
+       __BITFIELD_FIELD(unsigned int func : 11,
        ;)))))
 };
 
@@ -758,51 +758,51 @@ struct mm_x_format {              /* Scaled indexed load format (microMIPS) */
  * microMIPS instruction formats (16-bit length)
  */
 struct mm_b0_format {          /* Unconditional branch format (microMIPS) */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(signed int simmediate : 10,
-       BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(signed int simmediate : 10,
+       __BITFIELD_FIELD(unsigned int : 16, /* Ignored */
        ;)))
 };
 
 struct mm_b1_format {          /* Conditional branch format (microMIPS) */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int rs : 3,
-       BITFIELD_FIELD(signed int simmediate : 7,
-       BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int rs : 3,
+       __BITFIELD_FIELD(signed int simmediate : 7,
+       __BITFIELD_FIELD(unsigned int : 16, /* Ignored */
        ;))))
 };
 
 struct mm16_m_format {         /* Multi-word load/store format */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int func : 4,
-       BITFIELD_FIELD(unsigned int rlist : 2,
-       BITFIELD_FIELD(unsigned int imm : 4,
-       BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int func : 4,
+       __BITFIELD_FIELD(unsigned int rlist : 2,
+       __BITFIELD_FIELD(unsigned int imm : 4,
+       __BITFIELD_FIELD(unsigned int : 16, /* Ignored */
        ;)))))
 };
 
 struct mm16_rb_format {                /* Signed immediate format */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int rt : 3,
-       BITFIELD_FIELD(unsigned int base : 3,
-       BITFIELD_FIELD(signed int simmediate : 4,
-       BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int rt : 3,
+       __BITFIELD_FIELD(unsigned int base : 3,
+       __BITFIELD_FIELD(signed int simmediate : 4,
+       __BITFIELD_FIELD(unsigned int : 16, /* Ignored */
        ;)))))
 };
 
 struct mm16_r3_format {                /* Load from global pointer format */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int rt : 3,
-       BITFIELD_FIELD(signed int simmediate : 7,
-       BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int rt : 3,
+       __BITFIELD_FIELD(signed int simmediate : 7,
+       __BITFIELD_FIELD(unsigned int : 16, /* Ignored */
        ;))))
 };
 
 struct mm16_r5_format {                /* Load/store from stack pointer format */
-       BITFIELD_FIELD(unsigned int opcode : 6,
-       BITFIELD_FIELD(unsigned int rt : 5,
-       BITFIELD_FIELD(signed int simmediate : 5,
-       BITFIELD_FIELD(unsigned int : 16, /* Ignored */
+       __BITFIELD_FIELD(unsigned int opcode : 6,
+       __BITFIELD_FIELD(unsigned int rt : 5,
+       __BITFIELD_FIELD(signed int simmediate : 5,
+       __BITFIELD_FIELD(unsigned int : 16, /* Ignored */
        ;))))
 };
 
@@ -810,57 +810,57 @@ struct mm16_r5_format {           /* Load/store from stack pointer format */
  * MIPS16e instruction formats (16-bit length)
  */
 struct m16e_rr {
-       BITFIELD_FIELD(unsigned int opcode : 5,
-       BITFIELD_FIELD(unsigned int rx : 3,
-       BITFIELD_FIELD(unsigned int nd : 1,
-       BITFIELD_FIELD(unsigned int l : 1,
-       BITFIELD_FIELD(unsigned int ra : 1,
-       BITFIELD_FIELD(unsigned int func : 5,
+       __BITFIELD_FIELD(unsigned int opcode : 5,
+       __BITFIELD_FIELD(unsigned int rx : 3,
+       __BITFIELD_FIELD(unsigned int nd : 1,
+       __BITFIELD_FIELD(unsigned int l : 1,
+       __BITFIELD_FIELD(unsigned int ra : 1,
+       __BITFIELD_FIELD(unsigned int func : 5,
        ;))))))
 };
 
 struct m16e_jal {
-       BITFIELD_FIELD(unsigned int opcode : 5,
-       BITFIELD_FIELD(unsigned int x : 1,
-       BITFIELD_FIELD(unsigned int imm20_16 : 5,
-       BITFIELD_FIELD(signed int imm25_21 : 5,
+       __BITFIELD_FIELD(unsigned int opcode : 5,
+       __BITFIELD_FIELD(unsigned int x : 1,
+       __BITFIELD_FIELD(unsigned int imm20_16 : 5,
+       __BITFIELD_FIELD(signed int imm25_21 : 5,
        ;))))
 };
 
 struct m16e_i64 {
-       BITFIELD_FIELD(unsigned int opcode : 5,
-       BITFIELD_FIELD(unsigned int func : 3,
-       BITFIELD_FIELD(unsigned int imm : 8,
+       __BITFIELD_FIELD(unsigned int opcode : 5,
+       __BITFIELD_FIELD(unsigned int func : 3,
+       __BITFIELD_FIELD(unsigned int imm : 8,
        ;)))
 };
 
 struct m16e_ri64 {
-       BITFIELD_FIELD(unsigned int opcode : 5,
-       BITFIELD_FIELD(unsigned int func : 3,
-       BITFIELD_FIELD(unsigned int ry : 3,
-       BITFIELD_FIELD(unsigned int imm : 5,
+       __BITFIELD_FIELD(unsigned int opcode : 5,
+       __BITFIELD_FIELD(unsigned int func : 3,
+       __BITFIELD_FIELD(unsigned int ry : 3,
+       __BITFIELD_FIELD(unsigned int imm : 5,
        ;))))
 };
 
 struct m16e_ri {
-       BITFIELD_FIELD(unsigned int opcode : 5,
-       BITFIELD_FIELD(unsigned int rx : 3,
-       BITFIELD_FIELD(unsigned int imm : 8,
+       __BITFIELD_FIELD(unsigned int opcode : 5,
+       __BITFIELD_FIELD(unsigned int rx : 3,
+       __BITFIELD_FIELD(unsigned int imm : 8,
        ;)))
 };
 
 struct m16e_rri {
-       BITFIELD_FIELD(unsigned int opcode : 5,
-       BITFIELD_FIELD(unsigned int rx : 3,
-       BITFIELD_FIELD(unsigned int ry : 3,
-       BITFIELD_FIELD(unsigned int imm : 5,
+       __BITFIELD_FIELD(unsigned int opcode : 5,
+       __BITFIELD_FIELD(unsigned int rx : 3,
+       __BITFIELD_FIELD(unsigned int ry : 3,
+       __BITFIELD_FIELD(unsigned int imm : 5,
        ;))))
 };
 
 struct m16e_i8 {
-       BITFIELD_FIELD(unsigned int opcode : 5,
-       BITFIELD_FIELD(unsigned int func : 3,
-       BITFIELD_FIELD(unsigned int imm : 8,
+       __BITFIELD_FIELD(unsigned int opcode : 5,
+       __BITFIELD_FIELD(unsigned int func : 3,
+       __BITFIELD_FIELD(unsigned int imm : 8,
        ;)))
 };
 
index d6e154a9e6a55ef98d964f71629a129f6fd04d27..5805414777e0c66abd878a3b798c56809e0e57c5 100644 (file)
 #define __NR_finit_module              (__NR_Linux + 348)
 #define __NR_sched_setattr             (__NR_Linux + 349)
 #define __NR_sched_getattr             (__NR_Linux + 350)
+#define __NR_renameat2                 (__NR_Linux + 351)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls            350
+#define __NR_Linux_syscalls            351
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux                 4000
-#define __NR_O32_Linux_syscalls                350
+#define __NR_O32_Linux_syscalls                351
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
 #define __NR_getdents64                        (__NR_Linux + 308)
 #define __NR_sched_setattr             (__NR_Linux + 309)
 #define __NR_sched_getattr             (__NR_Linux + 310)
+#define __NR_renameat2                 (__NR_Linux + 311)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls            310
+#define __NR_Linux_syscalls            311
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux                  5000
-#define __NR_64_Linux_syscalls         310
+#define __NR_64_Linux_syscalls         311
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
 #define __NR_finit_module              (__NR_Linux + 312)
 #define __NR_sched_setattr             (__NR_Linux + 313)
 #define __NR_sched_getattr             (__NR_Linux + 314)
+#define __NR_renameat2                 (__NR_Linux + 315)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls            314
+#define __NR_Linux_syscalls            315
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux                 6000
-#define __NR_N32_Linux_syscalls                314
+#define __NR_N32_Linux_syscalls                315
 
 #endif /* _UAPI_ASM_UNISTD_H */
index 4d78bf445a9cd2e7397898ac32e24b4ee1bac8dd..76122ff5cb5ef877a7c0e6b3c55ecc6232f9c899 100644 (file)
@@ -317,7 +317,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
                if (regs->regs[insn.i_format.rs] ==
                    regs->regs[insn.i_format.rt]) {
                        epc = epc + 4 + (insn.i_format.simmediate << 2);
-                       if (insn.i_format.rt == beql_op)
+                       if (insn.i_format.opcode == beql_op)
                                ret = BRANCH_LIKELY_TAKEN;
                } else
                        epc += 8;
@@ -329,7 +329,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
                if (regs->regs[insn.i_format.rs] !=
                    regs->regs[insn.i_format.rt]) {
                        epc = epc + 4 + (insn.i_format.simmediate << 2);
-                       if (insn.i_format.rt == bnel_op)
+                       if (insn.i_format.opcode == bnel_op)
                                ret = BRANCH_LIKELY_TAKEN;
                } else
                        epc += 8;
@@ -341,7 +341,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
                /* rt field assumed to be zero */
                if ((long)regs->regs[insn.i_format.rs] <= 0) {
                        epc = epc + 4 + (insn.i_format.simmediate << 2);
-                       if (insn.i_format.rt == bnel_op)
+                       if (insn.i_format.opcode == blezl_op)
                                ret = BRANCH_LIKELY_TAKEN;
                } else
                        epc += 8;
@@ -353,7 +353,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
                /* rt field assumed to be zero */
                if ((long)regs->regs[insn.i_format.rs] > 0) {
                        epc = epc + 4 + (insn.i_format.simmediate << 2);
-                       if (insn.i_format.rt == bnel_op)
+                       if (insn.i_format.opcode == bgtzl_op)
                                ret = BRANCH_LIKELY_TAKEN;
                } else
                        epc += 8;
index e40971b51d2f0bf47e3eb217f43c652c732e7a09..037a44d962f37e1b94251f13b054103e6cbb1ff5 100644 (file)
@@ -124,14 +124,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        seq_printf(m, "kscratch registers\t: %d\n",
                      hweight8(cpu_data[n].kscratch_mask));
        seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core);
-#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
-       if (cpu_has_mipsmt) {
-               seq_printf(m, "VPE\t\t\t: %d\n", cpu_data[n].vpe_id);
-#if defined(CONFIG_MIPS_MT_SMTC)
-               seq_printf(m, "TC\t\t\t: %d\n", cpu_data[n].tc_id);
-#endif
-       }
-#endif
+
        sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
                      cpu_has_vce ? "%u" : "not available");
        seq_printf(m, fmt, 'D', vced_count);
index 71f85f4270341252d046db277aecfd5d3d0ae13d..f639ccd5060c18d85f33a33f2cc4bce81605ae3b 100644 (file)
@@ -163,7 +163,7 @@ int ptrace_get_watch_regs(struct task_struct *child,
        enum pt_watch_style style;
        int i;
 
-       if (!cpu_has_watch || current_cpu_data.watch_reg_use_cnt == 0)
+       if (!cpu_has_watch || boot_cpu_data.watch_reg_use_cnt == 0)
                return -EIO;
        if (!access_ok(VERIFY_WRITE, addr, sizeof(struct pt_watch_regs)))
                return -EIO;
@@ -177,14 +177,14 @@ int ptrace_get_watch_regs(struct task_struct *child,
 #endif
 
        __put_user(style, &addr->style);
-       __put_user(current_cpu_data.watch_reg_use_cnt,
+       __put_user(boot_cpu_data.watch_reg_use_cnt,
                   &addr->WATCH_STYLE.num_valid);
-       for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) {
+       for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) {
                __put_user(child->thread.watch.mips3264.watchlo[i],
                           &addr->WATCH_STYLE.watchlo[i]);
                __put_user(child->thread.watch.mips3264.watchhi[i] & 0xfff,
                           &addr->WATCH_STYLE.watchhi[i]);
-               __put_user(current_cpu_data.watch_reg_masks[i],
+               __put_user(boot_cpu_data.watch_reg_masks[i],
                           &addr->WATCH_STYLE.watch_masks[i]);
        }
        for (; i < 8; i++) {
@@ -204,12 +204,12 @@ int ptrace_set_watch_regs(struct task_struct *child,
        unsigned long lt[NUM_WATCH_REGS];
        u16 ht[NUM_WATCH_REGS];
 
-       if (!cpu_has_watch || current_cpu_data.watch_reg_use_cnt == 0)
+       if (!cpu_has_watch || boot_cpu_data.watch_reg_use_cnt == 0)
                return -EIO;
        if (!access_ok(VERIFY_READ, addr, sizeof(struct pt_watch_regs)))
                return -EIO;
        /* Check the values. */
-       for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) {
+       for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) {
                __get_user(lt[i], &addr->WATCH_STYLE.watchlo[i]);
 #ifdef CONFIG_32BIT
                if (lt[i] & __UA_LIMIT)
@@ -228,7 +228,7 @@ int ptrace_set_watch_regs(struct task_struct *child,
                        return -EINVAL;
        }
        /* Install them. */
-       for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) {
+       for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) {
                if (lt[i] & 7)
                        watch_active = 1;
                child->thread.watch.mips3264.watchlo[i] = lt[i];
index fdc70b40044265fb2107df186eb0e593a96b9571..3245474f19d5cdec5563a3841ecdcd3760f98e17 100644 (file)
@@ -577,3 +577,4 @@ EXPORT(sys_call_table)
        PTR     sys_finit_module
        PTR     sys_sched_setattr
        PTR     sys_sched_getattr               /* 4350 */
+       PTR     sys_renameat2
index dd99c3285aeae75f65ae982de46a755ae953f140..be2fedd4ae33193937010b376e62c7d9e327022d 100644 (file)
@@ -430,4 +430,5 @@ EXPORT(sys_call_table)
        PTR     sys_getdents64
        PTR     sys_sched_setattr
        PTR     sys_sched_getattr               /* 5310 */
+       PTR     sys_renameat2
        .size   sys_call_table,.-sys_call_table
index f68d2f4f009021de3ed784e9733aee5d3580d8e0..c1dbcda4b816844cc64821aa8d64a79d5c9a38f3 100644 (file)
@@ -423,4 +423,5 @@ EXPORT(sysn32_call_table)
        PTR     sys_finit_module
        PTR     sys_sched_setattr
        PTR     sys_sched_getattr
+       PTR     sys_renameat2                   /* 6315 */
        .size   sysn32_call_table,.-sysn32_call_table
index 70f6acecd928896c54b586b3470c27eb703721be..f1343ccd7ed7e58d14563c4413ede6517ff60853 100644 (file)
@@ -556,4 +556,5 @@ EXPORT(sys32_call_table)
        PTR     sys_finit_module
        PTR     sys_sched_setattr
        PTR     sys_sched_getattr               /* 4350 */
+       PTR     sys_renameat2
        .size   sys32_call_table,.-sys32_call_table
index 074e857ced284eb70bab2d8ae31ae496a14984b5..8119ac2fdfc9f67d098c14ee16f0e6c314bfe0f8 100644 (file)
@@ -1545,7 +1545,7 @@ asmlinkage void cache_parity_error(void)
               reg_val & (1<<30) ? "secondary" : "primary",
               reg_val & (1<<31) ? "data" : "insn");
        if (cpu_has_mips_r2 &&
-           ((current_cpu_data.processor_id && 0xff0000) == PRID_COMP_MIPS)) {
+           ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) {
                pr_err("Error bits: %s%s%s%s%s%s%s%s\n",
                        reg_val & (1<<29) ? "ED " : "",
                        reg_val & (1<<28) ? "ET " : "",
@@ -1585,7 +1585,7 @@ asmlinkage void do_ftlb(void)
 
        /* For the moment, report the problem and hang. */
        if (cpu_has_mips_r2 &&
-           ((current_cpu_data.processor_id && 0xff0000) == PRID_COMP_MIPS)) {
+           ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) {
                pr_err("FTLB error exception, cp0_ecc=0x%08x:\n",
                       read_c0_ecc());
                pr_err("cp0_errorepc == %0*lx\n", field, read_c0_errorepc());
index fac1f5b178ebe3c558ad369a9e1243340da04c80..143b8a37b5e41358f3faa814375869b058c9fee7 100644 (file)
@@ -8,6 +8,7 @@
        };
 
        memory@0 {
+               device_type = "memory";
                reg = <0x0 0x2000000>;
        };
 
index 2e4825e483882b217046caf4a847a99c3db56afe..9901237563c58922d213b9af10b9ed3c504b18e5 100644 (file)
 #define UNIT(unit)  ((unit)*NBYTES)
 
 #define ADDC(sum,reg)                                          \
+       .set    push;                                           \
+       .set    noat;                                           \
        ADD     sum, reg;                                       \
        sltu    v1, sum, reg;                                   \
        ADD     sum, v1;                                        \
+       .set    pop
 
 #define ADDC32(sum,reg)                                                \
+       .set    push;                                           \
+       .set    noat;                                           \
        addu    sum, reg;                                       \
        sltu    v1, sum, reg;                                   \
        addu    sum, v1;                                        \
+       .set    pop
 
 #define CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3)   \
        LOAD    _t0, (offset + UNIT(0))(src);                   \
@@ -710,6 +716,8 @@ LEAF(csum_partial)
        ADDC(sum, t2)
 .Ldone\@:
        /* fold checksum */
+       .set    push
+       .set    noat
 #ifdef USE_DOUBLE
        dsll32  v1, sum, 0
        daddu   sum, v1
@@ -732,6 +740,7 @@ LEAF(csum_partial)
        or      sum, sum, t0
 1:
 #endif
+       .set    pop
        .set reorder
        ADDC32(sum, psum)
        jr      ra
index 44713af15a62bc60ebc53ffcbc9e73ad10d87380..705cfb7c1a74e0843e40567219024882ab932ac9 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright (C) 1994 by Waldorf Electronics
  * Copyright (C) 1995 - 2000, 01, 03 by Ralf Baechle
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- * Copyright (C) 2007  Maciej W. Rozycki
+ * Copyright (C) 2007, 2014 Maciej W. Rozycki
  */
 #include <linux/module.h>
 #include <linux/param.h>
 #include <asm/compiler.h>
 #include <asm/war.h>
 
+#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
+#define GCC_DADDI_IMM_ASM() "I"
+#else
+#define GCC_DADDI_IMM_ASM() "r"
+#endif
+
 void __delay(unsigned long loops)
 {
        __asm__ __volatile__ (
@@ -22,13 +28,13 @@ void __delay(unsigned long loops)
        "       .align  3                                       \n"
        "1:     bnez    %0, 1b                                  \n"
 #if BITS_PER_LONG == 32
-       "       subu    %0,                                   \n"
+       "       subu    %0, %1                                  \n"
 #else
-       "       dsubu   %0,                                   \n"
+       "       dsubu   %0, %1                                  \n"
 #endif
        "       .set    reorder                                 \n"
        : "=r" (loops)
-       : "0" (loops));
+       : GCC_DADDI_IMM_ASM() (1), "0" (loops));
 }
 EXPORT_SYMBOL(__delay);
 
index d3301cd1e9a51b4c387a7f8c3d4a46e2632761e2..3c32baf8b49447a591e6e552e634eafe5be8d09e 100644 (file)
@@ -35,7 +35,6 @@ LEAF(__strncpy_from_\func\()_asm)
        bnez            v0, .Lfault\@
 
 FEXPORT(__strncpy_from_\func\()_nocheck_asm)
-       .set            noreorder
        move            t0, zero
        move            v1, a1
 .ifeqs "\func","kernel"
@@ -45,21 +44,21 @@ FEXPORT(__strncpy_from_\func\()_nocheck_asm)
 .endif
        PTR_ADDIU       v1, 1
        R10KCBARRIER(0(ra))
+       sb              v0, (a0)
        beqz            v0, 2f
-        sb             v0, (a0)
        PTR_ADDIU       t0, 1
+       PTR_ADDIU       a0, 1
        bne             t0, a2, 1b
-        PTR_ADDIU      a0, 1
 2:     PTR_ADDU        v0, a1, t0
        xor             v0, a1
        bltz            v0, .Lfault\@
-        nop
+       move            v0, t0
        jr              ra                      # return n
-        move           v0, t0
        END(__strncpy_from_\func\()_asm)
 
-.Lfault\@: jr          ra
-         li            v0, -EFAULT
+.Lfault\@:
+       li              v0, -EFAULT
+       jr              ra
 
        .section        __ex_table,"a"
        PTR             1b, .Lfault\@
index 7397be226a06a2a7d0481fac7b2dd476d4fe6d3a..603d79a95f4778e40d5ec94b78f1efa9750cd214 100644 (file)
@@ -64,7 +64,6 @@ config LEMOTE_MACH3A
        bool "Lemote Loongson 3A family machines"
        select ARCH_SPARSEMEM_ENABLE
        select GENERIC_ISA_DMA_SUPPORT_BROKEN
-       select GENERIC_HARDIRQS_NO__DO_IRQ
        select BOOT_ELF32
        select BOARD_SCACHE
        select CSRC_R4K
index c639b9db0012cbee3df5a24e21063c5af9832694..12c75db23420c70fd5ff7837a78554f15cecd606 100644 (file)
@@ -27,8 +27,7 @@
 
 #include <cs5536/cs5536_mfgpt.h>
 
-DEFINE_SPINLOCK(mfgpt_lock);
-EXPORT_SYMBOL(mfgpt_lock);
+static DEFINE_RAW_SPINLOCK(mfgpt_lock);
 
 static u32 mfgpt_base;
 
@@ -55,7 +54,7 @@ EXPORT_SYMBOL(enable_mfgpt0_counter);
 static void init_mfgpt_timer(enum clock_event_mode mode,
                             struct clock_event_device *evt)
 {
-       spin_lock(&mfgpt_lock);
+       raw_spin_lock(&mfgpt_lock);
 
        switch (mode) {
        case CLOCK_EVT_MODE_PERIODIC:
@@ -79,7 +78,7 @@ static void init_mfgpt_timer(enum clock_event_mode mode,
                /* Nothing to do here */
                break;
        }
-       spin_unlock(&mfgpt_lock);
+       raw_spin_unlock(&mfgpt_lock);
 }
 
 static struct clock_event_device mfgpt_clockevent = {
@@ -157,7 +156,7 @@ static cycle_t mfgpt_read(struct clocksource *cs)
        static int old_count;
        static u32 old_jifs;
 
-       spin_lock_irqsave(&mfgpt_lock, flags);
+       raw_spin_lock_irqsave(&mfgpt_lock, flags);
        /*
         * Although our caller may have the read side of xtime_lock,
         * this is now a seqlock, and we are cheating in this routine
@@ -191,7 +190,7 @@ static cycle_t mfgpt_read(struct clocksource *cs)
        old_count = count;
        old_jifs = jifs;
 
-       spin_unlock_irqrestore(&mfgpt_lock, flags);
+       raw_spin_unlock_irqrestore(&mfgpt_lock, flags);
 
        return (cycle_t) (jifs * COMPARE) + count;
 }
index e1f427f4f5f3fed4985bb370054421d7d2f91cdc..67dd94ef28e60f4023b16f7da8fac716c558b3bf 100644 (file)
@@ -91,6 +91,7 @@ EXPORT_SYMBOL(clk_put);
 
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
+       unsigned int rate_khz = rate / 1000;
        int ret = 0;
        int regval;
        int i;
@@ -111,10 +112,10 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
                if (loongson2_clockmod_table[i].frequency ==
                    CPUFREQ_ENTRY_INVALID)
                        continue;
-               if (rate == loongson2_clockmod_table[i].frequency)
+               if (rate_khz == loongson2_clockmod_table[i].frequency)
                        break;
        }
-       if (rate != loongson2_clockmod_table[i].frequency)
+       if (rate_khz != loongson2_clockmod_table[i].frequency)
                return -ENOTSUPP;
 
        clk->rate = rate;
index 58033c44690d75db10637e757168f96b5bb5dea7..b611102e23b5c72948ef5c5b8c1e12d603a0ff15 100644 (file)
@@ -273,7 +273,7 @@ void build_clear_page(void)
                uasm_i_ori(&buf, A2, A0, off);
 
        if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
-               uasm_i_lui(&buf, AT, 0xa000);
+               uasm_i_lui(&buf, AT, uasm_rel_hi(0xa0000000));
 
        off = cache_line_size ? min(8, pref_bias_clear_store / cache_line_size)
                                * cache_line_size : 0;
@@ -424,7 +424,7 @@ void build_copy_page(void)
                uasm_i_ori(&buf, A2, A0, off);
 
        if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
-               uasm_i_lui(&buf, AT, 0xa000);
+               uasm_i_lui(&buf, AT, uasm_rel_hi(0xa0000000));
 
        off = cache_line_size ? min(8, pref_bias_copy_load / cache_line_size) *
                                cache_line_size : 0;
index 30a494db99c2a0eb4d51aa64ca410de956801837..a5427c6e97574c6a1a0dbad628f7a75a3feed516 100644 (file)
 
 #define FASTPATH_SIZE  128
 
+EXPORT(tlbmiss_handler_setup_pgd_start)
 LEAF(tlbmiss_handler_setup_pgd)
-       .space          16 * 4
+1:     j       1b              /* Dummy, will be replaced. */
+       .space  64
 END(tlbmiss_handler_setup_pgd)
 EXPORT(tlbmiss_handler_setup_pgd_end)
 
index ee88367ab3addcda0e4aba412f524493dddd079a..f99ec587b151919bd90437687f08614c24aea32e 100644 (file)
@@ -1422,16 +1422,17 @@ static void build_r4000_tlb_refill_handler(void)
 extern u32 handle_tlbl[], handle_tlbl_end[];
 extern u32 handle_tlbs[], handle_tlbs_end[];
 extern u32 handle_tlbm[], handle_tlbm_end[];
-extern u32 tlbmiss_handler_setup_pgd[], tlbmiss_handler_setup_pgd_end[];
+extern u32 tlbmiss_handler_setup_pgd_start[], tlbmiss_handler_setup_pgd[];
+extern u32 tlbmiss_handler_setup_pgd_end[];
 
 static void build_setup_pgd(void)
 {
        const int a0 = 4;
        const int __maybe_unused a1 = 5;
        const int __maybe_unused a2 = 6;
-       u32 *p = tlbmiss_handler_setup_pgd;
+       u32 *p = tlbmiss_handler_setup_pgd_start;
        const int tlbmiss_handler_setup_pgd_size =
-               tlbmiss_handler_setup_pgd_end - tlbmiss_handler_setup_pgd;
+               tlbmiss_handler_setup_pgd_end - tlbmiss_handler_setup_pgd_start;
 #ifndef CONFIG_MIPS_PGD_C0_CONTEXT
        long pgdc = (long)pgd_current;
 #endif
index 6d0f4ab3632d01fa4b8474f3e02e388d0a1f0f89..f2364e41968282c5a5a8e3c4c954a9cb9ca8f18c 100644 (file)
@@ -27,7 +27,7 @@ unsigned long physical_memsize = 0L;
 fw_memblock_t * __init fw_getmdesc(int eva)
 {
        char *memsize_str, *ememsize_str __maybe_unused = NULL, *ptr;
-       unsigned long memsize, ememsize __maybe_unused = 0;
+       unsigned long memsize = 0, ememsize __maybe_unused = 0;
        static char cmdline[COMMAND_LINE_SIZE] __initdata;
        int tmp;
 
index b128cb973ebe6163ef5b3f8fa5704f1fc943a18f..7f6ce6d734c0c8b9f3f54a9358daff1f3f513924 100644 (file)
@@ -53,7 +53,6 @@ static struct resource rc32434_res_pci_mem1 = {
        .start = 0x50000000,
        .end = 0x5FFFFFFF,
        .flags = IORESOURCE_MEM,
-       .parent = &rc32434_res_pci_mem1,
        .sibling = NULL,
        .child = &rc32434_res_pci_mem2
 };
index 35eb874ab7f11b25248e40714c2e477ec0f1d4a3..709f58132f5cba9d87adc37afbe84c38db40a5ac 100644 (file)
@@ -7,6 +7,7 @@
        model = "Ralink MT7620A evaluation board";
 
        memory@0 {
+               device_type = "memory";
                reg = <0x0 0x2000000>;
        };
 
index 322d7002595bda983b95f9bb77a17de24980c001..0a685db093d4dbd367228a1cb9e4d42bdf43e0e7 100644 (file)
@@ -7,6 +7,7 @@
        model = "Ralink RT2880 evaluation board";
 
        memory@0 {
+               device_type = "memory";
                reg = <0x8000000 0x2000000>;
        };
 
index 0ac73ea281984909df89403d17fb82fd4e9f3ae4..ec9e9a03554140a4c11947b2ff0a7548cb4fb7fb 100644 (file)
@@ -7,6 +7,7 @@
        model = "Ralink RT3052 evaluation board";
 
        memory@0 {
+               device_type = "memory";
                reg = <0x0 0x2000000>;
        };
 
index 2fa6b330bf4f2fcb8d6f63f4b8df55cb1fe6b065..e8df21a5d10d9eb35a2dfc88af0d137d9c66156e 100644 (file)
@@ -7,6 +7,7 @@
        model = "Ralink RT3883 evaluation board";
 
        memory@0 {
+               device_type = "memory";
                reg = <0x0 0x2000000>;
        };
 
index 1faefed32749c93ff31a7d6237732d3dd6c55f26..108d48e652af4c802da1676b18252a5394d30295 100644 (file)
@@ -22,6 +22,7 @@ config PARISC
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_STRNCPY_FROM_USER
        select SYSCTL_ARCH_UNALIGN_ALLOW
+       select SYSCTL_EXCEPTION_TRACE
        select HAVE_MOD_ARCH_SPECIFIC
        select VIRT_TO_BUS
        select MODULES_USE_ELF_RELA
index 198a86feb5748fc595f7230941485af0bc84a76a..d951c9681ab316aa2be88cd65b4d18ae62f958cb 100644 (file)
 #define STACK_TOP      TASK_SIZE
 #define STACK_TOP_MAX  DEFAULT_TASK_SIZE
 
+/* Allow bigger stacks for 64-bit processes */
+#define STACK_SIZE_MAX (USER_WIDE_MODE                                 \
+                        ? (1 << 30)    /* 1 GB */                      \
+                        : (CONFIG_MAX_STACK_SIZE_MB*1024*1024))
+
 #endif
 
 #ifndef __ASSEMBLY__
index 265ae5190b0a70e4dc2539d9a661e1e3d2deda05..47e0e21d2272468bbc864e6e30ced36c18929534 100644 (file)
 #define __NR_sched_setattr     (__NR_Linux + 334)
 #define __NR_sched_getattr     (__NR_Linux + 335)
 #define __NR_utimes            (__NR_Linux + 336)
+#define __NR_renameat2         (__NR_Linux + 337)
 
-#define __NR_Linux_syscalls    (__NR_utimes + 1)
+#define __NR_Linux_syscalls    (__NR_renameat2 + 1)
 
 
 #define __IGNORE_select                /* newselect */
index 31ffa9b5532216620d9a6106d2d4b76e7501ee0b..e1ffea2f9a0b05ccda844969dcb7c519ab17077a 100644 (file)
@@ -72,10 +72,10 @@ static unsigned long mmap_upper_limit(void)
 {
        unsigned long stack_base;
 
-       /* Limit stack size to 1GB - see setup_arg_pages() in fs/exec.c */
+       /* Limit stack size - see setup_arg_pages() in fs/exec.c */
        stack_base = rlimit_max(RLIMIT_STACK);
-       if (stack_base > (1 << 30))
-               stack_base = 1 << 30;
+       if (stack_base > STACK_SIZE_MAX)
+               stack_base = STACK_SIZE_MAX;
 
        return PAGE_ALIGN(STACK_TOP - stack_base);
 }
index a63bb179f79a1fcd56a7bcf1adbe759f46587b71..83878601103701df4497913c89d5702897249a38 100644 (file)
@@ -589,10 +589,13 @@ cas_nocontend:
 # endif
 /* ENABLE_LWS_DEBUG */
 
+       rsm     PSW_SM_I, %r0                           /* Disable interrupts */
+       /* COW breaks can cause contention on UP systems */
        LDCW    0(%sr2,%r20), %r28                      /* Try to acquire the lock */
        cmpb,<>,n       %r0, %r28, cas_action           /* Did we get it? */
 cas_wouldblock:
        ldo     2(%r0), %r28                            /* 2nd case */
+       ssm     PSW_SM_I, %r0
        b       lws_exit                                /* Contended... */
        ldo     -EAGAIN(%r0), %r21                      /* Spin in userspace */
 
@@ -619,15 +622,17 @@ cas_action:
        stw     %r1, 4(%sr2,%r20)
 #endif
        /* The load and store could fail */
-1:     ldw     0(%sr3,%r26), %r28
+1:     ldw,ma  0(%sr3,%r26), %r28
        sub,<>  %r28, %r25, %r0
-2:     stw     %r24, 0(%sr3,%r26)
+2:     stw,ma  %r24, 0(%sr3,%r26)
        /* Free lock */
-       stw     %r20, 0(%sr2,%r20)
+       stw,ma  %r20, 0(%sr2,%r20)
 #if ENABLE_LWS_DEBUG
        /* Clear thread register indicator */
        stw     %r0, 4(%sr2,%r20)
 #endif
+       /* Enable interrupts */
+       ssm     PSW_SM_I, %r0
        /* Return to userspace, set no error */
        b       lws_exit
        copy    %r0, %r21
@@ -639,6 +644,7 @@ cas_action:
 #if ENABLE_LWS_DEBUG
        stw     %r0, 4(%sr2,%r20)
 #endif
+       ssm     PSW_SM_I, %r0
        b       lws_exit
        ldo     -EFAULT(%r0),%r21       /* set errno */
        nop
index 83ead0ea127d23cdcb10115a5b04d76f40e10612..c5fa7a697fba2a13b0779e59904ec7c1428e8ef4 100644 (file)
        ENTRY_SAME(sched_setattr)
        ENTRY_SAME(sched_getattr)       /* 335 */
        ENTRY_COMP(utimes)
+       ENTRY_SAME(renameat2)
 
        /* Nothing yet */
 
index 1cd1d0c83b6d7bd7a21d0a22c57e18f2ac27f65a..47ee620d15d27850ab8ebac1f739dfd3215dae9b 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/console.h>
 #include <linux/bug.h>
+#include <linux/ratelimit.h>
 
 #include <asm/assembly.h>
 #include <asm/uaccess.h>
@@ -42,9 +43,6 @@
 
 #include "../math-emu/math-emu.h"      /* for handle_fpe() */
 
-#define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */
-                         /*  dumped to the console via printk)          */
-
 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
 DEFINE_SPINLOCK(pa_dbit_lock);
 #endif
@@ -160,6 +158,17 @@ void show_regs(struct pt_regs *regs)
        }
 }
 
+static DEFINE_RATELIMIT_STATE(_hppa_rs,
+       DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST);
+
+#define parisc_printk_ratelimited(critical, regs, fmt, ...)    {             \
+       if ((critical || show_unhandled_signals) && __ratelimit(&_hppa_rs)) { \
+               printk(fmt, ##__VA_ARGS__);                                   \
+               show_regs(regs);                                              \
+       }                                                                     \
+}
+
+
 static void do_show_stack(struct unwind_frame_info *info)
 {
        int i = 1;
@@ -229,12 +238,10 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
                if (err == 0)
                        return; /* STFU */
 
-               printk(KERN_CRIT "%s (pid %d): %s (code %ld) at " RFMT "\n",
+               parisc_printk_ratelimited(1, regs,
+                       KERN_CRIT "%s (pid %d): %s (code %ld) at " RFMT "\n",
                        current->comm, task_pid_nr(current), str, err, regs->iaoq[0]);
-#ifdef PRINT_USER_FAULTS
-               /* XXX for debugging only */
-               show_regs(regs);
-#endif
+
                return;
        }
 
@@ -321,14 +328,11 @@ static void handle_break(struct pt_regs *regs)
                        (tt == BUG_TRAP_TYPE_NONE) ? 9 : 0);
        }
 
-#ifdef PRINT_USER_FAULTS
-       if (unlikely(iir != GDB_BREAK_INSN)) {
-               printk(KERN_DEBUG "break %d,%d: pid=%d command='%s'\n",
+       if (unlikely(iir != GDB_BREAK_INSN))
+               parisc_printk_ratelimited(0, regs,
+                       KERN_DEBUG "break %d,%d: pid=%d command='%s'\n",
                        iir & 31, (iir>>13) & ((1<<13)-1),
                        task_pid_nr(current), current->comm);
-               show_regs(regs);
-       }
-#endif
 
        /* send standard GDB signal */
        handle_gdb_break(regs, TRAP_BRKPT);
@@ -758,11 +762,9 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
 
        default:
                if (user_mode(regs)) {
-#ifdef PRINT_USER_FAULTS
-                       printk(KERN_DEBUG "\nhandle_interruption() pid=%d command='%s'\n",
-                           task_pid_nr(current), current->comm);
-                       show_regs(regs);
-#endif
+                       parisc_printk_ratelimited(0, regs, KERN_DEBUG
+                               "handle_interruption() pid=%d command='%s'\n",
+                               task_pid_nr(current), current->comm);
                        /* SIGBUS, for lack of a better one. */
                        si.si_signo = SIGBUS;
                        si.si_code = BUS_OBJERR;
@@ -779,16 +781,10 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
 
        if (user_mode(regs)) {
            if ((fault_space >> SPACEID_SHIFT) != (regs->sr[7] >> SPACEID_SHIFT)) {
-#ifdef PRINT_USER_FAULTS
-               if (fault_space == 0)
-                       printk(KERN_DEBUG "User Fault on Kernel Space ");
-               else
-                       printk(KERN_DEBUG "User Fault (long pointer) (fault %d) ",
-                              code);
-               printk(KERN_CONT "pid=%d command='%s'\n",
-                      task_pid_nr(current), current->comm);
-               show_regs(regs);
-#endif
+               parisc_printk_ratelimited(0, regs, KERN_DEBUG
+                               "User fault %d on space 0x%08lx, pid=%d command='%s'\n",
+                               code, fault_space,
+                               task_pid_nr(current), current->comm);
                si.si_signo = SIGSEGV;
                si.si_errno = 0;
                si.si_code = SEGV_MAPERR;
index 747550762f3ca25acf6dabdfcc7d8aef9de31779..3ca9c1131cfe0d80b9b12fb5c0e599a3363942c0 100644 (file)
 #include <asm/uaccess.h>
 #include <asm/traps.h>
 
-#define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */
-                        /*  dumped to the console via printk)          */
-
-
 /* Various important other fields */
 #define bit22set(x)            (x & 0x00000200)
 #define bits23_25set(x)                (x & 0x000001c0)
@@ -34,6 +30,8 @@
 
 DEFINE_PER_CPU(struct exception_data, exception_data);
 
+int show_unhandled_signals = 1;
+
 /*
  * parisc_acctyp(unsigned int inst) --
  *    Given a PA-RISC memory access instruction, determine if the
@@ -173,6 +171,32 @@ int fixup_exception(struct pt_regs *regs)
        return 0;
 }
 
+/*
+ * Print out info about fatal segfaults, if the show_unhandled_signals
+ * sysctl is set:
+ */
+static inline void
+show_signal_msg(struct pt_regs *regs, unsigned long code,
+               unsigned long address, struct task_struct *tsk,
+               struct vm_area_struct *vma)
+{
+       if (!unhandled_signal(tsk, SIGSEGV))
+               return;
+
+       if (!printk_ratelimit())
+               return;
+
+       pr_warn("\n");
+       pr_warn("do_page_fault() command='%s' type=%lu address=0x%08lx",
+           tsk->comm, code, address);
+       print_vma_addr(KERN_CONT " in ", regs->iaoq[0]);
+       if (vma)
+               pr_warn(" vm_start = 0x%08lx, vm_end = 0x%08lx\n",
+                               vma->vm_start, vma->vm_end);
+
+       show_regs(regs);
+}
+
 void do_page_fault(struct pt_regs *regs, unsigned long code,
                              unsigned long address)
 {
@@ -270,16 +294,8 @@ bad_area:
        if (user_mode(regs)) {
                struct siginfo si;
 
-#ifdef PRINT_USER_FAULTS
-               printk(KERN_DEBUG "\n");
-               printk(KERN_DEBUG "do_page_fault() pid=%d command='%s' type=%lu address=0x%08lx\n",
-                   task_pid_nr(tsk), tsk->comm, code, address);
-               if (vma) {
-                       printk(KERN_DEBUG "vm_start = 0x%08lx, vm_end = 0x%08lx\n",
-                                       vma->vm_start, vma->vm_end);
-               }
-               show_regs(regs);
-#endif
+               show_signal_msg(regs, code, address, tsk, vma);
+
                switch (code) {
                case 15:        /* Data TLB miss fault/Data page fault */
                        /* send SIGSEGV when outside of vma */
index 4c0cedf4e2c7dda768378223deb024c03a94b7c9..ce4c68a4a8236a4feb70c2b4a7291079d519dc98 100644 (file)
@@ -150,7 +150,9 @@ endif
 
 CFLAGS-$(CONFIG_TUNE_CELL) += $(call cc-option,-mtune=cell)
 
-KBUILD_CPPFLAGS        += -Iarch/$(ARCH)
+asinstr := $(call as-instr,lis 9$(comma)foo@high,-DHAVE_AS_ATHIGH=1)
+
+KBUILD_CPPFLAGS        += -Iarch/$(ARCH) $(asinstr)
 KBUILD_AFLAGS  += -Iarch/$(ARCH)
 KBUILD_CFLAGS  += -msoft-float -pipe -Iarch/$(ARCH) $(CFLAGS-y)
 CPP            = $(CC) -E $(KBUILD_CFLAGS)
index 6586a40a46ce161f9f654a57d0222db3bc06d611..cded7c1278ef0c419b134cabc74292209391b5c6 100644 (file)
@@ -318,11 +318,16 @@ n:
        addi    reg,reg,(name - 0b)@l;
 
 #ifdef __powerpc64__
+#ifdef HAVE_AS_ATHIGH
+#define __AS_ATHIGH high
+#else
+#define __AS_ATHIGH h
+#endif
 #define LOAD_REG_IMMEDIATE(reg,expr)           \
        lis     reg,(expr)@highest;             \
        ori     reg,reg,(expr)@higher;  \
        rldicr  reg,reg,32,31;          \
-       oris    reg,reg,(expr)@h;               \
+       oris    reg,reg,(expr)@__AS_ATHIGH;     \
        ori     reg,reg,(expr)@l;
 
 #define LOAD_REG_ADDR(reg,name)                        \
index d0e784e0ff484f0053f807e081a4c89fec13dee6..52179033067262f8f107be29c16b1fba6b8d4cee 100644 (file)
@@ -39,6 +39,17 @@ static inline int overlaps_kernel_text(unsigned long start, unsigned long end)
                (unsigned long)_stext < end;
 }
 
+static inline int overlaps_kvm_tmp(unsigned long start, unsigned long end)
+{
+#ifdef CONFIG_KVM_GUEST
+       extern char kvm_tmp[];
+       return start < (unsigned long)kvm_tmp &&
+               (unsigned long)&kvm_tmp[1024 * 1024] < end;
+#else
+       return 0;
+#endif
+}
+
 #undef dereference_function_descriptor
 static inline void *dereference_function_descriptor(void *ptr)
 {
index 3ddf70276706421532066e89261ea3f0d0c8c9ab..ea4dc3a89c1f05d91390cdf9c498029617fdf7f4 100644 (file)
@@ -361,3 +361,4 @@ SYSCALL(finit_module)
 SYSCALL(ni_syscall) /* sys_kcmp */
 SYSCALL_SPU(sched_setattr)
 SYSCALL_SPU(sched_getattr)
+SYSCALL_SPU(renameat2)
index 4494f029b632e50babb7d1d08c8535da144a43b1..9b892bbd9d843ec4d2af43f788a557b9e35bcec5 100644 (file)
@@ -12,7 +12,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define __NR_syscalls          357
+#define __NR_syscalls          358
 
 #define __NR__exit __NR_exit
 #define NR_syscalls    __NR_syscalls
index 881bf2e2560d40c05723d262da69402dcdfed262..2d526f7b48da121f60b2c3c7c069b07199a76ff6 100644 (file)
 #define __NR_kcmp              354
 #define __NR_sched_setattr     355
 #define __NR_sched_getattr     356
+#define __NR_renameat2         357
 
 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
index 6a0175297b0d8e92495ce97e7274ecba72fcb790..dd8695f6cb6d2c6de9bca80b073f4f40013cdeef 100644 (file)
@@ -74,7 +74,7 @@
 #define KVM_INST_MTSRIN                0x7c0001e4
 
 static bool kvm_patching_worked = true;
-static char kvm_tmp[1024 * 1024];
+char kvm_tmp[1024 * 1024];
 static int kvm_tmp_index;
 
 static inline void kvm_patch_ins(u32 *inst, u32 new_inst)
index 59d229a2a3e08dfcd1f18ca94e56cd00e787c987..879b3aacac3282d8b9de5101c9349d2aea9b8edc 100644 (file)
@@ -237,7 +237,7 @@ static void wake_offline_cpus(void)
                if (!cpu_online(cpu)) {
                        printk(KERN_INFO "kexec: Waking offline cpu %d.\n",
                               cpu);
-                       cpu_up(cpu);
+                       WARN_ON(cpu_up(cpu));
                }
        }
 }
index 122a580f732246c02c5e31c301078cb725435919..7e711bdcc6da5adb399e8ac0a55097e76317fe51 100644 (file)
@@ -813,9 +813,6 @@ static void __init clocksource_init(void)
 static int decrementer_set_next_event(unsigned long evt,
                                      struct clock_event_device *dev)
 {
-       /* Don't adjust the decrementer if some irq work is pending */
-       if (test_irq_work_pending())
-               return 0;
        __get_cpu_var(decrementers_next_tb) = get_tb_or_rtc() + evt;
        set_dec(evt);
 
index 94e597e6f15cd08f3f4f7deb5bab73d2d3ff1f27..7af190a266b388167693163f35eb5d249eee5d55 100644 (file)
@@ -886,7 +886,7 @@ static int kvmppc_book3s_init(void)
        r = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
        if (r)
                return r;
-#ifdef CONFIG_KVM_BOOK3S_32
+#ifdef CONFIG_KVM_BOOK3S_32_HANDLER
        r = kvmppc_book3s_init_pr();
 #endif
        return r;
@@ -895,7 +895,7 @@ static int kvmppc_book3s_init(void)
 
 static void kvmppc_book3s_exit(void)
 {
-#ifdef CONFIG_KVM_BOOK3S_32
+#ifdef CONFIG_KVM_BOOK3S_32_HANDLER
        kvmppc_book3s_exit_pr();
 #endif
        kvm_exit();
@@ -905,7 +905,7 @@ module_init(kvmppc_book3s_init);
 module_exit(kvmppc_book3s_exit);
 
 /* On 32bit this is our one and only kernel module */
-#ifdef CONFIG_KVM_BOOK3S_32
+#ifdef CONFIG_KVM_BOOK3S_32_HANDLER
 MODULE_ALIAS_MISCDEV(KVM_MINOR);
 MODULE_ALIAS("devname:kvm");
 #endif
index 1d6c56ad5b605f240770ed8ab6483f8b3fa00408..8fcc36306a02153dab0234e9f60558587715333f 100644 (file)
@@ -234,7 +234,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
                pte_size = psize;
                pte = lookup_linux_pte_and_update(pgdir, hva, writing,
                                                  &pte_size);
-               if (pte_present(pte)) {
+               if (pte_present(pte) && !pte_numa(pte)) {
                        if (writing && !pte_write(pte))
                                /* make the actual HPTE be read-only */
                                ptel = hpte_make_readonly(ptel);
index b031f932c0cc3dcc0c452c88f8ba2c3c88cf641d..07c8b5b0f9d256d80ef4853c741a882f7e4f560f 100644 (file)
@@ -1323,6 +1323,110 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
        mr      r3, r9
        bl      kvmppc_save_fp
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+BEGIN_FTR_SECTION
+       b       2f
+END_FTR_SECTION_IFCLR(CPU_FTR_TM)
+       /* Turn on TM. */
+       mfmsr   r8
+       li      r0, 1
+       rldimi  r8, r0, MSR_TM_LG, 63-MSR_TM_LG
+       mtmsrd  r8
+
+       ld      r5, VCPU_MSR(r9)
+       rldicl. r5, r5, 64 - MSR_TS_S_LG, 62
+       beq     1f      /* TM not active in guest. */
+
+       li      r3, TM_CAUSE_KVM_RESCHED
+
+       /* Clear the MSR RI since r1, r13 are all going to be foobar. */
+       li      r5, 0
+       mtmsrd  r5, 1
+
+       /* All GPRs are volatile at this point. */
+       TRECLAIM(R3)
+
+       /* Temporarily store r13 and r9 so we have some regs to play with */
+       SET_SCRATCH0(r13)
+       GET_PACA(r13)
+       std     r9, PACATMSCRATCH(r13)
+       ld      r9, HSTATE_KVM_VCPU(r13)
+
+       /* Get a few more GPRs free. */
+       std     r29, VCPU_GPRS_TM(29)(r9)
+       std     r30, VCPU_GPRS_TM(30)(r9)
+       std     r31, VCPU_GPRS_TM(31)(r9)
+
+       /* Save away PPR and DSCR soon so don't run with user values. */
+       mfspr   r31, SPRN_PPR
+       HMT_MEDIUM
+       mfspr   r30, SPRN_DSCR
+       ld      r29, HSTATE_DSCR(r13)
+       mtspr   SPRN_DSCR, r29
+
+       /* Save all but r9, r13 & r29-r31 */
+       reg = 0
+       .rept   29
+       .if (reg != 9) && (reg != 13)
+       std     reg, VCPU_GPRS_TM(reg)(r9)
+       .endif
+       reg = reg + 1
+       .endr
+       /* ... now save r13 */
+       GET_SCRATCH0(r4)
+       std     r4, VCPU_GPRS_TM(13)(r9)
+       /* ... and save r9 */
+       ld      r4, PACATMSCRATCH(r13)
+       std     r4, VCPU_GPRS_TM(9)(r9)
+
+       /* Reload stack pointer and TOC. */
+       ld      r1, HSTATE_HOST_R1(r13)
+       ld      r2, PACATOC(r13)
+
+       /* Set MSR RI now we have r1 and r13 back. */
+       li      r5, MSR_RI
+       mtmsrd  r5, 1
+
+       /* Save away checkpinted SPRs. */
+       std     r31, VCPU_PPR_TM(r9)
+       std     r30, VCPU_DSCR_TM(r9)
+       mflr    r5
+       mfcr    r6
+       mfctr   r7
+       mfspr   r8, SPRN_AMR
+       mfspr   r10, SPRN_TAR
+       std     r5, VCPU_LR_TM(r9)
+       stw     r6, VCPU_CR_TM(r9)
+       std     r7, VCPU_CTR_TM(r9)
+       std     r8, VCPU_AMR_TM(r9)
+       std     r10, VCPU_TAR_TM(r9)
+
+       /* Restore r12 as trap number. */
+       lwz     r12, VCPU_TRAP(r9)
+
+       /* Save FP/VSX. */
+       addi    r3, r9, VCPU_FPRS_TM
+       bl      .store_fp_state
+       addi    r3, r9, VCPU_VRS_TM
+       bl      .store_vr_state
+       mfspr   r6, SPRN_VRSAVE
+       stw     r6, VCPU_VRSAVE_TM(r9)
+1:
+       /*
+        * We need to save these SPRs after the treclaim so that the software
+        * error code is recorded correctly in the TEXASR.  Also the user may
+        * change these outside of a transaction, so they must always be
+        * context switched.
+        */
+       mfspr   r5, SPRN_TFHAR
+       mfspr   r6, SPRN_TFIAR
+       mfspr   r7, SPRN_TEXASR
+       std     r5, VCPU_TFHAR(r9)
+       std     r6, VCPU_TFIAR(r9)
+       std     r7, VCPU_TEXASR(r9)
+2:
+#endif
+
        /* Increment yield count if they have a VPA */
        ld      r8, VCPU_VPA(r9)        /* do they have a VPA? */
        cmpdi   r8, 0
index c5c052a9729c95d14591087fe71b20168237dc5d..02f1defd8bb9aa092dca510f4c80edeb45fafce6 100644 (file)
@@ -1153,7 +1153,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm,
                goto free_vcpu;
        vcpu->arch.book3s = vcpu_book3s;
 
-#ifdef CONFIG_KVM_BOOK3S_32
+#ifdef CONFIG_KVM_BOOK3S_32_HANDLER
        vcpu->arch.shadow_vcpu =
                kzalloc(sizeof(*vcpu->arch.shadow_vcpu), GFP_KERNEL);
        if (!vcpu->arch.shadow_vcpu)
@@ -1198,7 +1198,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm,
 uninit_vcpu:
        kvm_vcpu_uninit(vcpu);
 free_shadow_vcpu:
-#ifdef CONFIG_KVM_BOOK3S_32
+#ifdef CONFIG_KVM_BOOK3S_32_HANDLER
        kfree(vcpu->arch.shadow_vcpu);
 free_vcpu3s:
 #endif
@@ -1215,7 +1215,7 @@ static void kvmppc_core_vcpu_free_pr(struct kvm_vcpu *vcpu)
 
        free_page((unsigned long)vcpu->arch.shared & PAGE_MASK);
        kvm_vcpu_uninit(vcpu);
-#ifdef CONFIG_KVM_BOOK3S_32
+#ifdef CONFIG_KVM_BOOK3S_32_HANDLER
        kfree(vcpu->arch.shadow_vcpu);
 #endif
        vfree(vcpu_book3s);
index d766d6ee33fe6889e5a96b3898f8c47b0050fc14..06ba83b036d3360bb8750b1a869dfcf9e09705d0 100644 (file)
@@ -207,6 +207,10 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
                if (overlaps_kernel_text(vaddr, vaddr + step))
                        tprot &= ~HPTE_R_N;
 
+               /* Make kvm guest trampolines executable */
+               if (overlaps_kvm_tmp(vaddr, vaddr + step))
+                       tprot &= ~HPTE_R_N;
+
                /*
                 * If relocatable, check if it overlaps interrupt vectors that
                 * are copied down to real 0. For relocatable kernel
index 253fefe3d1a0e76fd4ed3996711b6f1784725d6c..5b51079f3e3ba52f7ecb51c3fb27a5d7255ebb48 100644 (file)
@@ -549,7 +549,8 @@ static int ioda_eeh_reset(struct eeh_pe *pe, int option)
                ret = ioda_eeh_phb_reset(hose, option);
        } else {
                bus = eeh_pe_bus_get(pe);
-               if (pci_is_root_bus(bus))
+               if (pci_is_root_bus(bus) ||
+                   pci_is_root_bus(bus->parent))
                        ret = ioda_eeh_root_reset(hose, option);
                else
                        ret = ioda_eeh_bridge_reset(hose, bus->self, option);
index cf3c0089bef253d7817a604f9a7f195a4ffd9bc0..23223cd63e54811d9ab85823df1e03303c88036e 100644 (file)
@@ -820,6 +820,9 @@ static int ctr_aes_crypt(struct blkcipher_desc *desc, long func,
                else
                        memcpy(walk->iv, ctrptr, AES_BLOCK_SIZE);
                spin_unlock(&ctrblk_lock);
+       } else {
+               if (!nbytes)
+                       memcpy(walk->iv, ctrptr, AES_BLOCK_SIZE);
        }
        /*
         * final block may be < AES_BLOCK_SIZE, copy only nbytes
index 0a5aac8a9412b64c4b2c43f9999e0f1e2f3815cb..7acb77f7ef1ada0183280c07e75f2c34579bac72 100644 (file)
@@ -429,6 +429,9 @@ static int ctr_desall_crypt(struct blkcipher_desc *desc, long func,
                else
                        memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE);
                spin_unlock(&ctrblk_lock);
+       } else {
+               if (!nbytes)
+                       memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE);
        }
        /* final block may be < DES_BLOCK_SIZE, copy only nbytes */
        if (nbytes) {
index b3ecb8f5b6ce2bcefb4fe92a64b99d2012cdd770..9ae6664ff08c768975ce452efa84c7cc9cdb0656 100644 (file)
@@ -158,6 +158,7 @@ int kvm_dev_ioctl_check_extension(long ext)
        case KVM_CAP_ONE_REG:
        case KVM_CAP_ENABLE_CAP:
        case KVM_CAP_S390_CSS_SUPPORT:
+       case KVM_CAP_IRQFD:
        case KVM_CAP_IOEVENTFD:
        case KVM_CAP_DEVICE_CTRL:
        case KVM_CAP_ENABLE_CAP_VM:
index 452d3ebd9d0fba3b513a6978b096bd22b27c1b46..e9f8fa9337fe1fae0d5d0ba9bf03a8426961a3c0 100644 (file)
@@ -811,7 +811,7 @@ static struct bpf_binary_header *bpf_alloc_binary(unsigned int bpfsize,
                return NULL;
        memset(header, 0, sz);
        header->pages = sz / PAGE_SIZE;
-       hole = sz - (bpfsize + sizeof(*header));
+       hole = min(sz - (bpfsize + sizeof(*header)), PAGE_SIZE - sizeof(*header));
        /* Insert random number of illegal instructions before BPF code
         * and make sure the first instruction starts at an even address.
         */
index 0f9e94537eee78d9d41fffe82e32fc0098811ed2..1a49ffdf9da91056cb24357b6fdefea772658201 100644 (file)
@@ -24,7 +24,8 @@
 
 /* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB).
  * The page copy blockops can use 0x6000000 to 0x8000000.
- * The TSB is mapped in the 0x8000000 to 0xa000000 range.
+ * The 8K TSB is mapped in the 0x8000000 to 0x8400000 range.
+ * The 4M TSB is mapped in the 0x8400000 to 0x8800000 range.
  * The PROM resides in an area spanning 0xf0000000 to 0x100000000.
  * The vmalloc area spans 0x100000000 to 0x200000000.
  * Since modules need to be in the lowest 32-bits of the address space,
@@ -33,7 +34,8 @@
  * 0x400000000.
  */
 #define        TLBTEMP_BASE            _AC(0x0000000006000000,UL)
-#define        TSBMAP_BASE             _AC(0x0000000008000000,UL)
+#define        TSBMAP_8K_BASE          _AC(0x0000000008000000,UL)
+#define        TSBMAP_4M_BASE          _AC(0x0000000008400000,UL)
 #define MODULES_VADDR          _AC(0x0000000010000000,UL)
 #define MODULES_LEN            _AC(0x00000000e0000000,UL)
 #define MODULES_END            _AC(0x00000000f0000000,UL)
 
 #include <linux/sched.h>
 
+extern unsigned long sparc64_valid_addr_bitmap[];
+
+/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+static inline bool __kern_addr_valid(unsigned long paddr)
+{
+       if ((paddr >> MAX_PHYS_ADDRESS_BITS) != 0UL)
+               return false;
+       return test_bit(paddr >> ILOG2_4MB, sparc64_valid_addr_bitmap);
+}
+
+static inline bool kern_addr_valid(unsigned long addr)
+{
+       unsigned long paddr = __pa(addr);
+
+       return __kern_addr_valid(paddr);
+}
+
 /* Entries per page directory level. */
 #define PTRS_PER_PTE   (1UL << (PAGE_SHIFT-3))
 #define PTRS_PER_PMD   (1UL << PMD_BITS)
 /* Kernel has a separate 44bit address space. */
 #define FIRST_USER_ADDRESS     0
 
-#define pte_ERROR(e)   __builtin_trap()
-#define pmd_ERROR(e)   __builtin_trap()
-#define pgd_ERROR(e)   __builtin_trap()
+#define pmd_ERROR(e)                                                   \
+       pr_err("%s:%d: bad pmd %p(%016lx) seen at (%pS)\n",             \
+              __FILE__, __LINE__, &(e), pmd_val(e), __builtin_return_address(0))
+#define pgd_ERROR(e)                                                   \
+       pr_err("%s:%d: bad pgd %p(%016lx) seen at (%pS)\n",             \
+              __FILE__, __LINE__, &(e), pgd_val(e), __builtin_return_address(0))
 
 #endif /* !(__ASSEMBLY__) */
 
@@ -258,8 +280,8 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
 {
        unsigned long mask, tmp;
 
-       /* SUN4U: 0x600307ffffffecb8 (negated == 0x9ffcf80000001347)
-        * SUN4V: 0x30ffffffffffee17 (negated == 0xcf000000000011e8)
+       /* SUN4U: 0x630107ffffffec38 (negated == 0x9cfef800000013c7)
+        * SUN4V: 0x33ffffffffffee07 (negated == 0xcc000000000011f8)
         *
         * Even if we use negation tricks the result is still a 6
         * instruction sequence, so don't try to play fancy and just
@@ -289,10 +311,10 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
        "       .previous\n"
        : "=r" (mask), "=r" (tmp)
        : "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U |
-              _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | _PAGE_PRESENT_4U |
+              _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U |
               _PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4U),
          "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
-              _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | _PAGE_PRESENT_4V |
+              _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V |
               _PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4V));
 
        return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask));
@@ -633,7 +655,7 @@ static inline unsigned long pmd_large(pmd_t pmd)
 {
        pte_t pte = __pte(pmd_val(pmd));
 
-       return (pte_val(pte) & _PAGE_PMD_HUGE) && pte_present(pte);
+       return pte_val(pte) & _PAGE_PMD_HUGE;
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -719,20 +741,6 @@ static inline pmd_t pmd_mkwrite(pmd_t pmd)
        return __pmd(pte_val(pte));
 }
 
-static inline pmd_t pmd_mknotpresent(pmd_t pmd)
-{
-       unsigned long mask;
-
-       if (tlb_type == hypervisor)
-               mask = _PAGE_PRESENT_4V;
-       else
-               mask = _PAGE_PRESENT_4U;
-
-       pmd_val(pmd) &= ~mask;
-
-       return pmd;
-}
-
 static inline pmd_t pmd_mksplitting(pmd_t pmd)
 {
        pte_t pte = __pte(pmd_val(pmd));
@@ -757,6 +765,20 @@ static inline int pmd_present(pmd_t pmd)
 
 #define pmd_none(pmd)                  (!pmd_val(pmd))
 
+/* pmd_bad() is only called on non-trans-huge PMDs.  Our encoding is
+ * very simple, it's just the physical address.  PTE tables are of
+ * size PAGE_SIZE so make sure the sub-PAGE_SIZE bits are clear and
+ * the top bits outside of the range of any physical address size we
+ * support are clear as well.  We also validate the physical itself.
+ */
+#define pmd_bad(pmd)                   ((pmd_val(pmd) & ~PAGE_MASK) || \
+                                        !__kern_addr_valid(pmd_val(pmd)))
+
+#define pud_none(pud)                  (!pud_val(pud))
+
+#define pud_bad(pud)                   ((pud_val(pud) & ~PAGE_MASK) || \
+                                        !__kern_addr_valid(pud_val(pud)))
+
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 extern void set_pmd_at(struct mm_struct *mm, unsigned long addr,
                       pmd_t *pmdp, pmd_t pmd);
@@ -790,10 +812,7 @@ static inline unsigned long __pmd_page(pmd_t pmd)
 #define pud_page_vaddr(pud)            \
        ((unsigned long) __va(pud_val(pud)))
 #define pud_page(pud)                  virt_to_page((void *)pud_page_vaddr(pud))
-#define pmd_bad(pmd)                   (0)
 #define pmd_clear(pmdp)                        (pmd_val(*(pmdp)) = 0UL)
-#define pud_none(pud)                  (!pud_val(pud))
-#define pud_bad(pud)                   (0)
 #define pud_present(pud)               (pud_val(pud) != 0U)
 #define pud_clear(pudp)                        (pud_val(*(pudp)) = 0UL)
 
@@ -893,6 +912,10 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *);
 extern void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
                                 pmd_t *pmd);
 
+#define __HAVE_ARCH_PMDP_INVALIDATE
+extern void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
+                           pmd_t *pmdp);
+
 #define __HAVE_ARCH_PGTABLE_DEPOSIT
 extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
                                       pgtable_t pgtable);
@@ -919,18 +942,6 @@ extern unsigned long pte_file(pte_t);
 extern pte_t pgoff_to_pte(unsigned long);
 #define PTE_FILE_MAX_BITS      (64UL - PAGE_SHIFT - 1UL)
 
-extern unsigned long sparc64_valid_addr_bitmap[];
-
-/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
-static inline bool kern_addr_valid(unsigned long addr)
-{
-       unsigned long paddr = __pa(addr);
-
-       if ((paddr >> 41UL) != 0UL)
-               return false;
-       return test_bit(paddr >> 22, sparc64_valid_addr_bitmap);
-}
-
 extern int page_in_phys_avail(unsigned long paddr);
 
 /*
index 2230f80d9fe326dc48576e83a721fcf106efeaf0..90916f955cac80153c59dc74a768c3fdef3fae56 100644 (file)
@@ -171,7 +171,8 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
        andcc           REG1, REG2, %g0;                \
        be,pt           %xcc, 700f;                     \
         sethi          %hi(4 * 1024 * 1024), REG2;     \
-       andn            REG1, REG2, REG1;               \
+       brgez,pn        REG1, FAIL_LABEL;               \
+        andn           REG1, REG2, REG1;               \
        and             VADDR, REG2, REG2;              \
        brlz,pt         REG1, PTE_LABEL;                \
         or             REG1, REG2, REG1;               \
index 26b706a1867dc6b9976b52e1e61ef8e54ce0df91..452f04fe8da698bb8b4620abd40ac6d4fbcd8393 100644 (file)
@@ -282,8 +282,8 @@ sun4v_chip_type:
        stx     %l2, [%l4 + 0x0]
        ldx     [%sp + 2047 + 128 + 0x50], %l3  ! physaddr low
        /* 4MB align */
-       srlx    %l3, 22, %l3
-       sllx    %l3, 22, %l3
+       srlx    %l3, ILOG2_4MB, %l3
+       sllx    %l3, ILOG2_4MB, %l3
        stx     %l3, [%l4 + 0x8]
 
        /* Leave service as-is, "call-method" */
index 542e96ac4d39948c165bd63eb9a43e25c0ba72e4..605d49204580585356a7fda6dede8657641fb7e1 100644 (file)
@@ -277,7 +277,7 @@ kvmap_dtlb_load:
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
 kvmap_vmemmap:
        sub             %g4, %g5, %g5
-       srlx            %g5, 22, %g5
+       srlx            %g5, ILOG2_4MB, %g5
        sethi           %hi(vmemmap_table), %g1
        sllx            %g5, 3, %g5
        or              %g1, %lo(vmemmap_table), %g1
index 6479256fd5a4b650a2f5c3ca3cf5c501033dc9fb..3370945569162dd43ef1252f47c83cf6ad7d87d6 100644 (file)
@@ -68,27 +68,16 @@ EXPORT_SYMBOL(touch_nmi_watchdog);
 
 static void die_nmi(const char *str, struct pt_regs *regs, int do_panic)
 {
+       int this_cpu = smp_processor_id();
+
        if (notify_die(DIE_NMIWATCHDOG, str, regs, 0,
                       pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP)
                return;
 
-       console_verbose();
-       bust_spinlocks(1);
-
-       printk(KERN_EMERG "%s", str);
-       printk(" on CPU%d, ip %08lx, registers:\n",
-              smp_processor_id(), regs->tpc);
-       show_regs(regs);
-       dump_stack();
-
-       bust_spinlocks(0);
-
        if (do_panic || panic_on_oops)
-               panic("Non maskable interrupt");
-
-       nmi_exit();
-       local_irq_enable();
-       do_exit(SIGBUS);
+               panic("Watchdog detected hard LOCKUP on cpu %d", this_cpu);
+       else
+               WARN(1, "Watchdog detected hard LOCKUP on cpu %d", this_cpu);
 }
 
 notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
index 9781048161ab8865a3ce203074d4067312989b95..745a3633ce148208554a71a38c829d6a8c78e025 100644 (file)
@@ -149,7 +149,7 @@ void cpu_panic(void)
 #define NUM_ROUNDS     64      /* magic value */
 #define NUM_ITERS      5       /* likewise */
 
-static DEFINE_SPINLOCK(itc_sync_lock);
+static DEFINE_RAW_SPINLOCK(itc_sync_lock);
 static unsigned long go[SLAVE + 1];
 
 #define DEBUG_TICK_SYNC        0
@@ -257,7 +257,7 @@ static void smp_synchronize_one_tick(int cpu)
        go[MASTER] = 0;
        membar_safe("#StoreLoad");
 
-       spin_lock_irqsave(&itc_sync_lock, flags);
+       raw_spin_lock_irqsave(&itc_sync_lock, flags);
        {
                for (i = 0; i < NUM_ROUNDS*NUM_ITERS; i++) {
                        while (!go[MASTER])
@@ -268,7 +268,7 @@ static void smp_synchronize_one_tick(int cpu)
                        membar_safe("#StoreLoad");
                }
        }
-       spin_unlock_irqrestore(&itc_sync_lock, flags);
+       raw_spin_unlock_irqrestore(&itc_sync_lock, flags);
 }
 
 #if defined(CONFIG_SUN_LDOMS) && defined(CONFIG_HOTPLUG_CPU)
index f7c72b6efc27556cd2e2de7a74539b1ba21831ce..d066eb18650c1598f898f7a4314bdd7ed5b606a7 100644 (file)
@@ -44,7 +44,7 @@ SIGN1(sys32_timer_settime, compat_sys_timer_settime, %o1)
 SIGN1(sys32_io_submit, compat_sys_io_submit, %o1)
 SIGN1(sys32_mq_open, compat_sys_mq_open, %o1)
 SIGN1(sys32_select, compat_sys_select, %o0)
-SIGN3(sys32_futex, compat_sys_futex, %o1, %o2, %o5)
+SIGN1(sys32_futex, compat_sys_futex, %o1)
 SIGN1(sys32_recvfrom, compat_sys_recvfrom, %o0)
 SIGN1(sys32_recvmsg, compat_sys_recvmsg, %o0)
 SIGN1(sys32_sendmsg, compat_sys_sendmsg, %o0)
index a364000ca1aa8a495f7e8b9bf59882350f41c6de..7f41d40b7e6e8ccf89b5ce12a9422bbf4e84ac2e 100644 (file)
@@ -151,7 +151,7 @@ static ssize_t store_mmustat_enable(struct device *s,
                        size_t count)
 {
        unsigned long val, err;
-       int ret = sscanf(buf, "%ld", &val);
+       int ret = sscanf(buf, "%lu", &val);
 
        if (ret != 1)
                return -EINVAL;
index 3c1a7cb31579fd0fe55e68bced2dc11757734c35..35ab8b60d25609220c1b1d10c1495642ea3700b2 100644 (file)
@@ -166,17 +166,23 @@ static unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs)
 unsigned long compute_effective_address(struct pt_regs *regs,
                                        unsigned int insn, unsigned int rd)
 {
+       int from_kernel = (regs->tstate & TSTATE_PRIV) != 0;
        unsigned int rs1 = (insn >> 14) & 0x1f;
        unsigned int rs2 = insn & 0x1f;
-       int from_kernel = (regs->tstate & TSTATE_PRIV) != 0;
+       unsigned long addr;
 
        if (insn & 0x2000) {
                maybe_flush_windows(rs1, 0, rd, from_kernel);
-               return (fetch_reg(rs1, regs) + sign_extend_imm13(insn));
+               addr = (fetch_reg(rs1, regs) + sign_extend_imm13(insn));
        } else {
                maybe_flush_windows(rs1, rs2, rd, from_kernel);
-               return (fetch_reg(rs1, regs) + fetch_reg(rs2, regs));
+               addr = (fetch_reg(rs1, regs) + fetch_reg(rs2, regs));
        }
+
+       if (!from_kernel && test_thread_flag(TIF_32BIT))
+               addr &= 0xffffffff;
+
+       return addr;
 }
 
 /* This is just to make gcc think die_if_kernel does return... */
index 2c20ad63ddbf2bbf8a4da5e751e49650d8be7060..30eee6e8a81b2d45797aab304914b10571573b1a 100644 (file)
@@ -236,6 +236,7 @@ FUNC_NAME:  /* %o0=dst, %o1=src, %o2=len */
         */
        VISEntryHalf
 
+       membar          #Sync
        alignaddr       %o1, %g0, %g0
 
        add             %o1, (64 - 1), %o4
index 69bb818fdd798b8d50dff44a46a9941272972a92..4ced3fc66130c30b8870c21cea57611056046d50 100644 (file)
@@ -96,38 +96,51 @@ static unsigned int get_user_insn(unsigned long tpc)
        pte_t *ptep, pte;
        unsigned long pa;
        u32 insn = 0;
-       unsigned long pstate;
 
-       if (pgd_none(*pgdp))
-               goto outret;
+       if (pgd_none(*pgdp) || unlikely(pgd_bad(*pgdp)))
+               goto out;
        pudp = pud_offset(pgdp, tpc);
-       if (pud_none(*pudp))
-               goto outret;
-       pmdp = pmd_offset(pudp, tpc);
-       if (pmd_none(*pmdp))
-               goto outret;
+       if (pud_none(*pudp) || unlikely(pud_bad(*pudp)))
+               goto out;
 
        /* This disables preemption for us as well. */
-       __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate));
-       __asm__ __volatile__("wrpr %0, %1, %%pstate"
-                               : : "r" (pstate), "i" (PSTATE_IE));
-       ptep = pte_offset_map(pmdp, tpc);
-       pte = *ptep;
-       if (!pte_present(pte))
-               goto out;
+       local_irq_disable();
+
+       pmdp = pmd_offset(pudp, tpc);
+       if (pmd_none(*pmdp) || unlikely(pmd_bad(*pmdp)))
+               goto out_irq_enable;
 
-       pa  = (pte_pfn(pte) << PAGE_SHIFT);
-       pa += (tpc & ~PAGE_MASK);
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+       if (pmd_trans_huge(*pmdp)) {
+               if (pmd_trans_splitting(*pmdp))
+                       goto out_irq_enable;
 
-       /* Use phys bypass so we don't pollute dtlb/dcache. */
-       __asm__ __volatile__("lduwa [%1] %2, %0"
-                            : "=r" (insn)
-                            : "r" (pa), "i" (ASI_PHYS_USE_EC));
+               pa  = pmd_pfn(*pmdp) << PAGE_SHIFT;
+               pa += tpc & ~HPAGE_MASK;
 
+               /* Use phys bypass so we don't pollute dtlb/dcache. */
+               __asm__ __volatile__("lduwa [%1] %2, %0"
+                                    : "=r" (insn)
+                                    : "r" (pa), "i" (ASI_PHYS_USE_EC));
+       } else
+#endif
+       {
+               ptep = pte_offset_map(pmdp, tpc);
+               pte = *ptep;
+               if (pte_present(pte)) {
+                       pa  = (pte_pfn(pte) << PAGE_SHIFT);
+                       pa += (tpc & ~PAGE_MASK);
+
+                       /* Use phys bypass so we don't pollute dtlb/dcache. */
+                       __asm__ __volatile__("lduwa [%1] %2, %0"
+                                            : "=r" (insn)
+                                            : "r" (pa), "i" (ASI_PHYS_USE_EC));
+               }
+               pte_unmap(ptep);
+       }
+out_irq_enable:
+       local_irq_enable();
 out:
-       pte_unmap(ptep);
-       __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate));
-outret:
        return insn;
 }
 
@@ -153,7 +166,8 @@ show_signal_msg(struct pt_regs *regs, int sig, int code,
 }
 
 static void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
-                            unsigned int insn, int fault_code)
+                            unsigned long fault_addr, unsigned int insn,
+                            int fault_code)
 {
        unsigned long addr;
        siginfo_t info;
@@ -161,10 +175,18 @@ static void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
        info.si_code = code;
        info.si_signo = sig;
        info.si_errno = 0;
-       if (fault_code & FAULT_CODE_ITLB)
+       if (fault_code & FAULT_CODE_ITLB) {
                addr = regs->tpc;
-       else
-               addr = compute_effective_address(regs, insn, 0);
+       } else {
+               /* If we were able to probe the faulting instruction, use it
+                * to compute a precise fault address.  Otherwise use the fault
+                * time provided address which may only have page granularity.
+                */
+               if (insn)
+                       addr = compute_effective_address(regs, insn, 0);
+               else
+                       addr = fault_addr;
+       }
        info.si_addr = (void __user *) addr;
        info.si_trapno = 0;
 
@@ -239,7 +261,7 @@ static void __kprobes do_kernel_fault(struct pt_regs *regs, int si_code,
                /* The si_code was set to make clear whether
                 * this was a SEGV_MAPERR or SEGV_ACCERR fault.
                 */
-               do_fault_siginfo(si_code, SIGSEGV, regs, insn, fault_code);
+               do_fault_siginfo(si_code, SIGSEGV, regs, address, insn, fault_code);
                return;
        }
 
@@ -259,18 +281,6 @@ static void noinline __kprobes bogus_32bit_fault_tpc(struct pt_regs *regs)
        show_regs(regs);
 }
 
-static void noinline __kprobes bogus_32bit_fault_address(struct pt_regs *regs,
-                                                        unsigned long addr)
-{
-       static int times;
-
-       if (times++ < 10)
-               printk(KERN_ERR "FAULT[%s:%d]: 32-bit process "
-                      "reports 64-bit fault address [%lx]\n",
-                      current->comm, current->pid, addr);
-       show_regs(regs);
-}
-
 asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
 {
        enum ctx_state prev_state = exception_enter();
@@ -300,10 +310,8 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
                                goto intr_or_no_mm;
                        }
                }
-               if (unlikely((address >> 32) != 0)) {
-                       bogus_32bit_fault_address(regs, address);
+               if (unlikely((address >> 32) != 0))
                        goto intr_or_no_mm;
-               }
        }
 
        if (regs->tstate & TSTATE_PRIV) {
@@ -525,7 +533,7 @@ do_sigbus:
         * Send a sigbus, regardless of whether we were in kernel
         * or user mode.
         */
-       do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, insn, fault_code);
+       do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, address, insn, fault_code);
 
        /* Kernel mode? Handle exceptions or die */
        if (regs->tstate & TSTATE_PRIV)
index c4d3da68b800db27e54761add314e4a882f4e4c6..1aed0432c64bab8344ad524ed28b835381588035 100644 (file)
@@ -73,7 +73,7 @@ static int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
        struct page *head, *page, *tail;
        int refs;
 
-       if (!pmd_large(pmd))
+       if (!(pmd_val(pmd) & _PAGE_VALID))
                return 0;
 
        if (write && !pmd_write(pmd))
index eafbc65c9c47f63772162d384ef55fd549d1e149..ed3c969a5f4c897e802b02dcfce583acabcf3a14 100644 (file)
@@ -588,7 +588,7 @@ static void __init remap_kernel(void)
        int i, tlb_ent = sparc64_highest_locked_tlbent();
 
        tte_vaddr = (unsigned long) KERNBASE;
-       phys_page = (prom_boot_mapping_phys_low >> 22UL) << 22UL;
+       phys_page = (prom_boot_mapping_phys_low >> ILOG2_4MB) << ILOG2_4MB;
        tte_data = kern_large_tte(phys_page);
 
        kern_locked_tte_data = tte_data;
@@ -1881,7 +1881,7 @@ void __init paging_init(void)
 
        BUILD_BUG_ON(NR_CPUS > 4096);
 
-       kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL;
+       kern_base = (prom_boot_mapping_phys_low >> ILOG2_4MB) << ILOG2_4MB;
        kern_size = (unsigned long)&_end - (unsigned long)KERNBASE;
 
        /* Invalidate both kernel TSBs.  */
@@ -1937,7 +1937,7 @@ void __init paging_init(void)
        shift = kern_base + PAGE_OFFSET - ((unsigned long)KERNBASE);
 
        real_end = (unsigned long)_end;
-       num_kernel_image_mappings = DIV_ROUND_UP(real_end - KERNBASE, 1 << 22);
+       num_kernel_image_mappings = DIV_ROUND_UP(real_end - KERNBASE, 1 << ILOG2_4MB);
        printk("Kernel: Using %d locked TLB entries for main kernel image.\n",
               num_kernel_image_mappings);
 
@@ -2094,7 +2094,7 @@ static void __init setup_valid_addr_bitmap_from_pavail(unsigned long *bitmap)
 
                                if (new_start <= old_start &&
                                    new_end >= (old_start + PAGE_SIZE)) {
-                                       set_bit(old_start >> 22, bitmap);
+                                       set_bit(old_start >> ILOG2_4MB, bitmap);
                                        goto do_next_page;
                                }
                        }
@@ -2143,7 +2143,7 @@ void __init mem_init(void)
        addr = PAGE_OFFSET + kern_base;
        last = PAGE_ALIGN(kern_size) + addr;
        while (addr < last) {
-               set_bit(__pa(addr) >> 22, sparc64_valid_addr_bitmap);
+               set_bit(__pa(addr) >> ILOG2_4MB, sparc64_valid_addr_bitmap);
                addr += PAGE_SIZE;
        }
 
@@ -2267,7 +2267,7 @@ int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
                void *block;
 
                if (!(*vmem_pp & _PAGE_VALID)) {
-                       block = vmemmap_alloc_block(1UL << 22, node);
+                       block = vmemmap_alloc_block(1UL << ILOG2_4MB, node);
                        if (!block)
                                return -ENOMEM;
 
index b12cb5e72812140688d771ed0788b6a2cf2cfc16..b89aba217e3b5105c3fae5737cca2f279db4dc95 100644 (file)
@@ -134,7 +134,7 @@ no_cache_flush:
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 static void tlb_batch_pmd_scan(struct mm_struct *mm, unsigned long vaddr,
-                              pmd_t pmd, bool exec)
+                              pmd_t pmd)
 {
        unsigned long end;
        pte_t *pte;
@@ -142,8 +142,11 @@ static void tlb_batch_pmd_scan(struct mm_struct *mm, unsigned long vaddr,
        pte = pte_offset_map(&pmd, vaddr);
        end = vaddr + HPAGE_SIZE;
        while (vaddr < end) {
-               if (pte_val(*pte) & _PAGE_VALID)
+               if (pte_val(*pte) & _PAGE_VALID) {
+                       bool exec = pte_exec(*pte);
+
                        tlb_batch_add_one(mm, vaddr, exec);
+               }
                pte++;
                vaddr += PAGE_SIZE;
        }
@@ -177,19 +180,30 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
        }
 
        if (!pmd_none(orig)) {
-               pte_t orig_pte = __pte(pmd_val(orig));
-               bool exec = pte_exec(orig_pte);
-
                addr &= HPAGE_MASK;
                if (pmd_trans_huge(orig)) {
+                       pte_t orig_pte = __pte(pmd_val(orig));
+                       bool exec = pte_exec(orig_pte);
+
                        tlb_batch_add_one(mm, addr, exec);
                        tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec);
                } else {
-                       tlb_batch_pmd_scan(mm, addr, orig, exec);
+                       tlb_batch_pmd_scan(mm, addr, orig);
                }
        }
 }
 
+void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
+                    pmd_t *pmdp)
+{
+       pmd_t entry = *pmdp;
+
+       pmd_val(entry) &= ~_PAGE_VALID;
+
+       set_pmd_at(vma->vm_mm, address, pmdp, entry);
+       flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
+}
+
 void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
                                pgtable_t pgtable)
 {
index f5d506fdddad3dea459aa97308e9a8872f34ffe8..fe19b81acc091b4d994da81f5580fe4438664388 100644 (file)
@@ -133,7 +133,19 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign
        mm->context.tsb_block[tsb_idx].tsb_nentries =
                tsb_bytes / sizeof(struct tsb);
 
-       base = TSBMAP_BASE;
+       switch (tsb_idx) {
+       case MM_TSB_BASE:
+               base = TSBMAP_8K_BASE;
+               break;
+#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
+       case MM_TSB_HUGE:
+               base = TSBMAP_4M_BASE;
+               break;
+#endif
+       default:
+               BUG();
+       }
+
        tte = pgprot_val(PAGE_KERNEL_LOCKED);
        tsb_paddr = __pa(mm->context.tsb_block[tsb_idx].tsb);
        BUG_ON(tsb_paddr & (tsb_bytes - 1UL));
index ce6ad7e6a7d7c7ba743884bbee2bcf77262f814d..33f71b01fd22e74d5e3d80b26ce4694689642064 100644 (file)
@@ -79,6 +79,7 @@ else
         UTS_MACHINE := x86_64
         CHECKFLAGS += -D__x86_64__ -m64
 
+        biarch := -m64
         KBUILD_AFLAGS += -m64
         KBUILD_CFLAGS += -m64
 
index abb9eba61b500192cd816dd9283fe8c8fb70b858..dbe8dd2fe247fb0632a79d5a20d1b4714729c47d 100644 (file)
@@ -71,7 +71,7 @@ $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
 
 SETUP_OBJS = $(addprefix $(obj)/,$(setup-y))
 
-sed-voffset := -e 's/^\([0-9a-fA-F]*\) . \(_text\|_end\)$$/\#define VO_\2 0x\1/p'
+sed-voffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(_text\|_end\)$$/\#define VO_\2 0x\1/p'
 
 quiet_cmd_voffset = VOFFSET $@
       cmd_voffset = $(NM) $< | sed -n $(sed-voffset) > $@
@@ -80,7 +80,7 @@ targets += voffset.h
 $(obj)/voffset.h: vmlinux FORCE
        $(call if_changed,voffset)
 
-sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
+sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
 
 quiet_cmd_zoffset = ZOFFSET $@
       cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@
index 17684615374b269f2d2eee0a826ab04d4eaf0f22..57ab74df7eeaa3eef4954b89f36d20b4c528afd7 100644 (file)
@@ -354,7 +354,7 @@ static void parse_elf(void *output)
        free(phdrs);
 }
 
-asmlinkage void *decompress_kernel(void *rmode, memptr heap,
+asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
                                  unsigned char *input_data,
                                  unsigned long input_len,
                                  unsigned char *output,
index b18df579c0e99b09ff33261e692135338826de3a..36f7125945e3e241cdf2ac825124fd8d7883e0ba 100644 (file)
@@ -63,6 +63,7 @@
 /* hpet memory map physical address */
 extern unsigned long hpet_address;
 extern unsigned long force_hpet_address;
+extern int boot_hpet_disable;
 extern u8 hpet_blockid;
 extern int hpet_force_user;
 extern u8 hpet_msi_disable;
index a8091216963b006145baa000e905edbdececae63..68c05398bba9b449a1324d54b584ce52d52aa8d1 100644 (file)
@@ -52,6 +52,7 @@ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
 static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
                                         unsigned long addr, pte_t *ptep)
 {
+       ptep_clear_flush(vma, addr, ptep);
 }
 
 static inline int huge_pte_none(pte_t pte)
index 8de6d9cf3b954a7f31bcb756c92c20cc08db5759..678205195ae118e16ca34609a24f472d9875e568 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _ASM_X86_PAGE_64_DEFS_H
 #define _ASM_X86_PAGE_64_DEFS_H
 
-#define THREAD_SIZE_ORDER      1
+#define THREAD_SIZE_ORDER      2
 #define THREAD_SIZE  (PAGE_SIZE << THREAD_SIZE_ORDER)
 #define CURRENT_MASK (~(THREAD_SIZE - 1))
 
index e709884d0ef9edbdd0b7228f180814bef1c0b174..ca08a27b90b3dbcf64dc69515fdadd3734b7a05e 100644 (file)
@@ -343,7 +343,7 @@ HYPERVISOR_memory_op(unsigned int cmd, void *arg)
 }
 
 static inline int
-HYPERVISOR_multicall(void *call_list, int nr_calls)
+HYPERVISOR_multicall(void *call_list, uint32_t nr_calls)
 {
        return _hypercall2(int, multicall, call_list, nr_calls);
 }
index fd9cb7695b5f444266abebafe6c3fcfa59e2d66b..3400dbaec3c31eb6e5097715521b6aaaa1cf8740 100644 (file)
@@ -54,6 +54,9 @@ typedef unsigned long xen_pfn_t;
 #define PRI_xen_pfn "lx"
 typedef unsigned long xen_ulong_t;
 #define PRI_xen_ulong "lx"
+typedef long xen_long_t;
+#define PRI_xen_long "lx"
+
 /* Guest handles for primitive C types. */
 __DEFINE_GUEST_HANDLE(uchar, unsigned char);
 __DEFINE_GUEST_HANDLE(uint,  unsigned int);
index c827ace3121bc0f7ff3dc9d4cc74024207adc68c..fcf2b3ae1bf0208d9e6b153dc81c6b0ed60f8352 100644 (file)
 #define MSR_IA32_MISC_ENABLE_MWAIT_BIT                 18
 #define MSR_IA32_MISC_ENABLE_MWAIT                     (1ULL << MSR_IA32_MISC_ENABLE_MWAIT_BIT)
 #define MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT           22
-#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID               (1ULL << MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT);
+#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID               (1ULL << MSR_IA32_MISC_ENABLE_LIMIT_CPUID_BIT)
 #define MSR_IA32_MISC_ENABLE_XTPR_DISABLE_BIT          23
 #define MSR_IA32_MISC_ENABLE_XTPR_DISABLE              (1ULL << MSR_IA32_MISC_ENABLE_XTPR_DISABLE_BIT)
 #define MSR_IA32_MISC_ENABLE_XD_DISABLE_BIT            34
index 3a2ae4c88948dcadb5b9afbfc2e10ef502202930..31368207837c2fbcd93f73d94ccf9c2d572d5cf5 100644 (file)
@@ -31,7 +31,7 @@ static char temp_stack[4096];
  *
  * Wrapper around acpi_enter_sleep_state() to be called by assmebly.
  */
-acpi_status asmlinkage x86_acpi_enter_sleep_state(u8 state)
+acpi_status asmlinkage __visible x86_acpi_enter_sleep_state(u8 state)
 {
        return acpi_enter_sleep_state(state);
 }
index d23aa82e7a7bc25c702be004f804a0c9d02c15f7..992060e09897dd2b068f8d8ebf6f02fa15fa2845 100644 (file)
@@ -2189,7 +2189,7 @@ void send_cleanup_vector(struct irq_cfg *cfg)
        cfg->move_in_progress = 0;
 }
 
-asmlinkage void smp_irq_move_cleanup_interrupt(void)
+asmlinkage __visible void smp_irq_move_cleanup_interrupt(void)
 {
        unsigned vector, me;
 
index d921b7ee659525e7d040ff5ea5c6a569239a64a7..36a1bb6d1ee0d431752a170714aa6a43576ffada 100644 (file)
@@ -429,14 +429,14 @@ static inline void __smp_thermal_interrupt(void)
        smp_thermal_vector();
 }
 
-asmlinkage void smp_thermal_interrupt(struct pt_regs *regs)
+asmlinkage __visible void smp_thermal_interrupt(struct pt_regs *regs)
 {
        entering_irq();
        __smp_thermal_interrupt();
        exiting_ack_irq();
 }
 
-asmlinkage void smp_trace_thermal_interrupt(struct pt_regs *regs)
+asmlinkage __visible void smp_trace_thermal_interrupt(struct pt_regs *regs)
 {
        entering_irq();
        trace_thermal_apic_entry(THERMAL_APIC_VECTOR);
index fe6b1c86645b668758331b78d93ab8c549ab09c2..7245980186eea047e643af5010e1509bfc991632 100644 (file)
@@ -24,14 +24,14 @@ static inline void __smp_threshold_interrupt(void)
        mce_threshold_vector();
 }
 
-asmlinkage void smp_threshold_interrupt(void)
+asmlinkage __visible void smp_threshold_interrupt(void)
 {
        entering_irq();
        __smp_threshold_interrupt();
        exiting_ack_irq();
 }
 
-asmlinkage void smp_trace_threshold_interrupt(void)
+asmlinkage __visible void smp_trace_threshold_interrupt(void)
 {
        entering_irq();
        trace_threshold_apic_entry(THRESHOLD_APIC_VECTOR);
index aa333d9668866f808955209f8cd71737d447eafc..adb02aa62af5e310ff51ca720d1163b247489ccb 100644 (file)
@@ -169,7 +169,6 @@ static struct event_constraint intel_slm_event_constraints[] __read_mostly =
 {
        FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
        FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
-       FIXED_EVENT_CONSTRAINT(0x013c, 2), /* CPU_CLK_UNHALTED.REF */
        FIXED_EVENT_CONSTRAINT(0x0300, 2), /* pseudo CPU_CLK_UNHALTED.REF */
        EVENT_CONSTRAINT_END
 };
index 384df5105fbc9883626ec5482151babd43ce482a..136ac74dee823005cea04ea9600a0c62cdf5685c 100644 (file)
@@ -27,6 +27,7 @@
 static int __init x86_rdrand_setup(char *s)
 {
        setup_clear_cpu_cap(X86_FEATURE_RDRAND);
+       setup_clear_cpu_cap(X86_FEATURE_RDSEED);
        return 1;
 }
 __setup("nordrand", x86_rdrand_setup);
index 6e2537c3219060b31a9344c5df0dd90d8d3afbd2..6cda0baeac9d7810dadbfadc9b9cb2b228c68c5e 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/dma.h>
 #include <asm/io_apic.h>
 #include <asm/apic.h>
+#include <asm/hpet.h>
 #include <asm/iommu.h>
 #include <asm/gart.h>
 #include <asm/irq_remapping.h>
@@ -530,6 +531,15 @@ static void __init intel_graphics_stolen(int num, int slot, int func)
        }
 }
 
+static void __init force_disable_hpet(int num, int slot, int func)
+{
+#ifdef CONFIG_HPET_TIMER
+       boot_hpet_disable = 1;
+       pr_info("x86/hpet: Will disable the HPET for this platform because it's not reliable\n");
+#endif
+}
+
+
 #define QFLAG_APPLY_ONCE       0x1
 #define QFLAG_APPLIED          0x2
 #define QFLAG_DONE             (QFLAG_APPLY_ONCE|QFLAG_APPLIED)
@@ -567,6 +577,12 @@ static struct chipset early_qrk[] __initdata = {
          PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check },
        { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA, PCI_ANY_ID,
          QFLAG_APPLY_ONCE, intel_graphics_stolen },
+       /*
+        * HPET on current version of Baytrail platform has accuracy
+        * problems, disable it for now:
+        */
+       { PCI_VENDOR_ID_INTEL, 0x0f00,
+               PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, force_disable_hpet},
        {}
 };
 
index c61a14a4a3109f92ee63bb4df2ba470540c1d266..d6c1b983699576523aacb5b8066d48311eb94a67 100644 (file)
@@ -29,7 +29,7 @@ static void __init i386_default_early_setup(void)
        reserve_ebda_region();
 }
 
-asmlinkage void __init i386_start_kernel(void)
+asmlinkage __visible void __init i386_start_kernel(void)
 {
        sanitize_boot_params(&boot_params);
 
index 85126ccbdf6b1e957c231a73378cc1ffe78092e8..068054f4bf20b75e124d4776ee9ffa889a6e1a0c 100644 (file)
@@ -137,7 +137,7 @@ static void __init copy_bootdata(char *real_mode_data)
        }
 }
 
-asmlinkage void __init x86_64_start_kernel(char * real_mode_data)
+asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
 {
        int i;
 
index 8d80ae0116039b6c71945737befc4f88dea097df..4177bfbc80b0d44400c563fa46affdbe79bc25d9 100644 (file)
@@ -88,7 +88,7 @@ static inline void hpet_clear_mapping(void)
 /*
  * HPET command line enable / disable
  */
-static int boot_hpet_disable;
+int boot_hpet_disable;
 int hpet_force_user;
 static int hpet_verbose;
 
index af1d14a9ebdae1ac2fddace4c15271babd1613a3..dcbbaa165bdeed61dd2b504a13ca05ced99737c7 100644 (file)
@@ -20,6 +20,8 @@
 #include <asm/mmu_context.h>
 #include <asm/syscalls.h>
 
+int sysctl_ldt16 = 0;
+
 #ifdef CONFIG_SMP
 static void flush_ldt(void *current_mm)
 {
@@ -234,7 +236,7 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
         * IRET leaking the high bits of the kernel stack address.
         */
 #ifdef CONFIG_X86_64
-       if (!ldt_info.seg_32bit) {
+       if (!ldt_info.seg_32bit && !sysctl_ldt16) {
                error = -EINVAL;
                goto out_unlock;
        }
index 9c0280f93d05dbf9b644abd040b472b9c69d4f55..898d077617a99ab7c6ef055b06f409c8222a4249 100644 (file)
@@ -52,7 +52,7 @@
 
 asmlinkage extern void ret_from_fork(void);
 
-asmlinkage DEFINE_PER_CPU(unsigned long, old_rsp);
+__visible DEFINE_PER_CPU(unsigned long, old_rsp);
 
 /* Prints also some state that isn't saved in the pt_regs */
 void __show_regs(struct pt_regs *regs, int all)
index 3399d3a997303322a9b5dc425080dd3553f98594..52b1157c53eb7f275b22d4a74def7daced321a80 100644 (file)
@@ -191,6 +191,16 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
                },
        },
 
+       /* Certec */
+       {       /* Handle problems with rebooting on Certec BPC600 */
+               .callback = set_pci_reboot,
+               .ident = "Certec BPC600",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Certec"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "BPC600"),
+               },
+       },
+
        /* Dell */
        {       /* Handle problems with rebooting on Dell DXP061 */
                .callback = set_bios_reboot,
index 7c3a5a61f2e46384c22abdf761afb4611d1efae6..be8e1bde07aa47ff373f0245e0f4b7d6d2edcfd5 100644 (file)
@@ -168,7 +168,7 @@ static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs)
  * this function calls the 'stop' function on all other CPUs in the system.
  */
 
-asmlinkage void smp_reboot_interrupt(void)
+asmlinkage __visible void smp_reboot_interrupt(void)
 {
        ack_APIC_irq();
        irq_enter();
index 57409f6b8c623e38c1a60dfa1029bb9d194c99e6..f73b5d435bdca59ff7c12c157a36997773fc2e07 100644 (file)
@@ -357,7 +357,7 @@ exit:
  * for scheduling or signal handling. The actual stack switch is done in
  * entry.S
  */
-asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
+asmlinkage __visible __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
 {
        struct pt_regs *regs = eregs;
        /* Did already sync */
@@ -601,11 +601,11 @@ do_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
 #endif
 }
 
-asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void)
+asmlinkage __visible void __attribute__((weak)) smp_thermal_interrupt(void)
 {
 }
 
-asmlinkage void __attribute__((weak)) smp_threshold_interrupt(void)
+asmlinkage __visible void __attribute__((weak)) smp_threshold_interrupt(void)
 {
 }
 
index 5edc34b5b9514df1f63af487a314ab4053d197a2..b99b9ad8540c525f79468d6fce0682681478c008 100644 (file)
@@ -36,7 +36,7 @@ static int irq_routing_comply = 1;
  * and vice versa.
  */
 
-asmlinkage unsigned long vsmp_save_fl(void)
+asmlinkage __visible unsigned long vsmp_save_fl(void)
 {
        unsigned long flags = native_save_fl();
 
@@ -56,7 +56,7 @@ __visible void vsmp_restore_fl(unsigned long flags)
 }
 PV_CALLEE_SAVE_REGS_THUNK(vsmp_restore_fl);
 
-asmlinkage void vsmp_irq_disable(void)
+asmlinkage __visible void vsmp_irq_disable(void)
 {
        unsigned long flags = native_save_fl();
 
@@ -64,7 +64,7 @@ asmlinkage void vsmp_irq_disable(void)
 }
 PV_CALLEE_SAVE_REGS_THUNK(vsmp_irq_disable);
 
-asmlinkage void vsmp_irq_enable(void)
+asmlinkage __visible void vsmp_irq_enable(void)
 {
        unsigned long flags = native_save_fl();
 
index f9c6e56e14b5f31229b75721db9975dac5fe58c9..9531fbb123ba2223257f48dd724b59a45289389c 100644 (file)
@@ -43,7 +43,7 @@ void update_vsyscall(struct timekeeper *tk)
        vdata->monotonic_time_sec       = tk->xtime_sec
                                        + tk->wall_to_monotonic.tv_sec;
        vdata->monotonic_time_snsec     = tk->xtime_nsec
-                                       + (tk->wall_to_monotonic.tv_nsec
+                                       + ((u64)tk->wall_to_monotonic.tv_nsec
                                                << tk->shift);
        while (vdata->monotonic_time_snsec >=
                                        (((u64)NSEC_PER_SEC) << tk->shift)) {
index 33e8c028842fb4b0b59bc269a973b195a104cdf8..138ceffc6377bba9e2c4fb5529ad379f81b0bec6 100644 (file)
@@ -7778,7 +7778,8 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
 
        exec_control = vmcs12->pin_based_vm_exec_control;
        exec_control |= vmcs_config.pin_based_exec_ctrl;
-       exec_control &= ~PIN_BASED_VMX_PREEMPTION_TIMER;
+       exec_control &= ~(PIN_BASED_VMX_PREEMPTION_TIMER |
+                          PIN_BASED_POSTED_INTR);
        vmcs_write32(PIN_BASED_VM_EXEC_CONTROL, exec_control);
 
        vmx->nested.preemption_timer_expired = false;
@@ -7815,7 +7816,9 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
                if (!vmx->rdtscp_enabled)
                        exec_control &= ~SECONDARY_EXEC_RDTSCP;
                /* Take the following fields only from vmcs12 */
-               exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+               exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
+                                 SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
+                                  SECONDARY_EXEC_APIC_REGISTER_VIRT);
                if (nested_cpu_has(vmcs12,
                                CPU_BASED_ACTIVATE_SECONDARY_CONTROLS))
                        exec_control |= vmcs12->secondary_vm_exec_control;
index 8b8fc0b792baeddf76a1b0ee3dac3a6a9b5cd0de..20316c67b824a9d06baa89cc0cf905eae3f24665 100644 (file)
@@ -106,6 +106,8 @@ EXPORT_SYMBOL_GPL(kvm_max_guest_tsc_khz);
 static u32 tsc_tolerance_ppm = 250;
 module_param(tsc_tolerance_ppm, uint, S_IRUGO | S_IWUSR);
 
+static bool backwards_tsc_observed = false;
+
 #define KVM_NR_SHARED_MSRS 16
 
 struct kvm_shared_msrs_global {
@@ -280,7 +282,7 @@ int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 }
 EXPORT_SYMBOL_GPL(kvm_set_apic_base);
 
-asmlinkage void kvm_spurious_fault(void)
+asmlinkage __visible void kvm_spurious_fault(void)
 {
        /* Fault while not rebooting.  We want the trace. */
        BUG();
@@ -1486,7 +1488,8 @@ static void pvclock_update_vm_gtod_copy(struct kvm *kvm)
                                        &ka->master_kernel_ns,
                                        &ka->master_cycle_now);
 
-       ka->use_master_clock = host_tsc_clocksource & vcpus_matched;
+       ka->use_master_clock = host_tsc_clocksource && vcpus_matched
+                               && !backwards_tsc_observed;
 
        if (ka->use_master_clock)
                atomic_set(&kvm_guest_has_master_clock, 1);
@@ -6945,6 +6948,7 @@ int kvm_arch_hardware_enable(void *garbage)
         */
        if (backwards_tsc) {
                u64 delta_cyc = max_tsc - local_tsc;
+               backwards_tsc_observed = true;
                list_for_each_entry(kvm, &vm_list, vm_list) {
                        kvm_for_each_vcpu(i, vcpu, kvm) {
                                vcpu->arch.tsc_offset_adjustment += delta_cyc;
index ad1fb5f53925e8634fac38da497128fed1904c55..aae94132bc24dd42b548d3dc18214b668195c06f 100644 (file)
@@ -233,13 +233,13 @@ static void lguest_end_context_switch(struct task_struct *next)
  * flags word contains all kind of stuff, but in practice Linux only cares
  * about the interrupt flag.  Our "save_flags()" just returns that.
  */
-asmlinkage unsigned long lguest_save_fl(void)
+asmlinkage __visible unsigned long lguest_save_fl(void)
 {
        return lguest_data.irq_enabled;
 }
 
 /* Interrupts go off... */
-asmlinkage void lguest_irq_disable(void)
+asmlinkage __visible void lguest_irq_disable(void)
 {
        lguest_data.irq_enabled = 0;
 }
index db9db446b71a66fe5bd59de47232e8fa69e8c96e..43623739c7cf315038f908d9623e601d8069c35b 100644 (file)
@@ -76,7 +76,7 @@ static inline int __flip_bit(u32 msr, u8 bit, bool set)
        if (m1.q == m.q)
                return 0;
 
-       err = msr_write(msr, &m);
+       err = msr_write(msr, &m1);
        if (err)
                return err;
 
index a5449089cd9fef6e58a03174c5fe5a34cd48983a..9e6545f269e548e7cff7f4ee51876c440a7b6706 100644 (file)
@@ -302,7 +302,7 @@ static struct {
              0x242  in div_Xsig.S
  */
 
-asmlinkage void FPU_exception(int n)
+asmlinkage __visible void FPU_exception(int n)
 {
        int i, int_type;
 
@@ -492,7 +492,7 @@ int real_2op_NaN(FPU_REG const *b, u_char tagb,
 
 /* Invalid arith operation on Valid registers */
 /* Returns < 0 if the exception is unmasked */
-asmlinkage int arith_invalid(int deststnr)
+asmlinkage __visible int arith_invalid(int deststnr)
 {
 
        EXCEPTION(EX_Invalid);
@@ -507,7 +507,7 @@ asmlinkage int arith_invalid(int deststnr)
 }
 
 /* Divide a finite number by zero */
-asmlinkage int FPU_divide_by_zero(int deststnr, u_char sign)
+asmlinkage __visible int FPU_divide_by_zero(int deststnr, u_char sign)
 {
        FPU_REG *dest = &st(deststnr);
        int tag = TAG_Valid;
@@ -539,7 +539,7 @@ int set_precision_flag(int flags)
 }
 
 /* This may be called often, so keep it lean */
-asmlinkage void set_precision_flag_up(void)
+asmlinkage __visible void set_precision_flag_up(void)
 {
        if (control_word & CW_Precision)
                partial_status |= (SW_Precision | SW_C1);       /* The masked response */
@@ -548,7 +548,7 @@ asmlinkage void set_precision_flag_up(void)
 }
 
 /* This may be called often, so keep it lean */
-asmlinkage void set_precision_flag_down(void)
+asmlinkage __visible void set_precision_flag_down(void)
 {
        if (control_word & CW_Precision) {      /* The masked response */
                partial_status &= ~SW_C1;
@@ -557,7 +557,7 @@ asmlinkage void set_precision_flag_down(void)
                EXCEPTION(EX_Precision);
 }
 
-asmlinkage int denormal_operand(void)
+asmlinkage __visible int denormal_operand(void)
 {
        if (control_word & CW_Denormal) {       /* The masked response */
                partial_status |= SW_Denorm_Op;
@@ -568,7 +568,7 @@ asmlinkage int denormal_operand(void)
        }
 }
 
-asmlinkage int arith_overflow(FPU_REG *dest)
+asmlinkage __visible int arith_overflow(FPU_REG *dest)
 {
        int tag = TAG_Valid;
 
@@ -596,7 +596,7 @@ asmlinkage int arith_overflow(FPU_REG *dest)
 
 }
 
-asmlinkage int arith_underflow(FPU_REG *dest)
+asmlinkage __visible int arith_underflow(FPU_REG *dest)
 {
        int tag = TAG_Valid;
 
index dc017735bb91b7b2ec61f333b091c63accdb921b..6d5663a599a7a362756b5bcb6d3ff3e30ee34bae 100644 (file)
@@ -171,7 +171,7 @@ static struct bpf_binary_header *bpf_alloc_binary(unsigned int proglen,
        memset(header, 0xcc, sz); /* fill whole space with int3 instructions */
 
        header->pages = sz / PAGE_SIZE;
-       hole = sz - (proglen + sizeof(*header));
+       hole = min(sz - (proglen + sizeof(*header)), PAGE_SIZE - sizeof(*header));
 
        /* insert a random number of int3 instructions before BPF code */
        *image_ptr = &header->image[prandom_u32() % hole];
index 81b506d5befd46e5a494d6cbef7aa71edceca7f1..524142117296898237466e9630da1dadd8bbe1fd 100644 (file)
 
 static const struct font_desc *font;
 static u32 efi_x, efi_y;
+static void *efi_fb;
+static bool early_efi_keep;
 
-static __init void early_efi_clear_scanline(unsigned int y)
+/*
+ * efi earlyprintk need use early_ioremap to map the framebuffer.
+ * But early_ioremap is not usable for earlyprintk=efi,keep, ioremap should
+ * be used instead. ioremap will be available after paging_init() which is
+ * earlier than initcall callbacks. Thus adding this early initcall function
+ * early_efi_map_fb to map the whole efi framebuffer.
+ */
+static __init int early_efi_map_fb(void)
 {
-       unsigned long base, *dst;
-       u16 len;
+       unsigned long base, size;
+
+       if (!early_efi_keep)
+               return 0;
 
        base = boot_params.screen_info.lfb_base;
-       len = boot_params.screen_info.lfb_linelength;
+       size = boot_params.screen_info.lfb_size;
+       efi_fb = ioremap(base, size);
+
+       return efi_fb ? 0 : -ENOMEM;
+}
+early_initcall(early_efi_map_fb);
+
+/*
+ * early_efi_map maps efi framebuffer region [start, start + len -1]
+ * In case earlyprintk=efi,keep we have the whole framebuffer mapped already
+ * so just return the offset efi_fb + start.
+ */
+static __init_refok void *early_efi_map(unsigned long start, unsigned long len)
+{
+       unsigned long base;
+
+       base = boot_params.screen_info.lfb_base;
+
+       if (efi_fb)
+               return (efi_fb + start);
+       else
+               return early_ioremap(base + start, len);
+}
 
-       dst = early_ioremap(base + y*len, len);
+static __init_refok void early_efi_unmap(void *addr, unsigned long len)
+{
+       if (!efi_fb)
+               early_iounmap(addr, len);
+}
+
+static void early_efi_clear_scanline(unsigned int y)
+{
+       unsigned long *dst;
+       u16 len;
+
+       len = boot_params.screen_info.lfb_linelength;
+       dst = early_efi_map(y*len, len);
        if (!dst)
                return;
 
        memset(dst, 0, len);
-       early_iounmap(dst, len);
+       early_efi_unmap(dst, len);
 }
 
-static __init void early_efi_scroll_up(void)
+static void early_efi_scroll_up(void)
 {
-       unsigned long base, *dst, *src;
+       unsigned long *dst, *src;
        u16 len;
        u32 i, height;
 
-       base = boot_params.screen_info.lfb_base;
        len = boot_params.screen_info.lfb_linelength;
        height = boot_params.screen_info.lfb_height;
 
        for (i = 0; i < height - font->height; i++) {
-               dst = early_ioremap(base + i*len, len);
+               dst = early_efi_map(i*len, len);
                if (!dst)
                        return;
 
-               src = early_ioremap(base + (i + font->height) * len, len);
+               src = early_efi_map((i + font->height) * len, len);
                if (!src) {
-                       early_iounmap(dst, len);
+                       early_efi_unmap(dst, len);
                        return;
                }
 
                memmove(dst, src, len);
 
-               early_iounmap(src, len);
-               early_iounmap(dst, len);
+               early_efi_unmap(src, len);
+               early_efi_unmap(dst, len);
        }
 }
 
@@ -79,16 +123,14 @@ static void early_efi_write_char(u32 *dst, unsigned char c, unsigned int h)
        }
 }
 
-static __init void
+static void
 early_efi_write(struct console *con, const char *str, unsigned int num)
 {
        struct screen_info *si;
-       unsigned long base;
        unsigned int len;
        const char *s;
        void *dst;
 
-       base = boot_params.screen_info.lfb_base;
        si = &boot_params.screen_info;
        len = si->lfb_linelength;
 
@@ -109,7 +151,7 @@ early_efi_write(struct console *con, const char *str, unsigned int num)
                for (h = 0; h < font->height; h++) {
                        unsigned int n, x;
 
-                       dst = early_ioremap(base + (efi_y + h) * len, len);
+                       dst = early_efi_map((efi_y + h) * len, len);
                        if (!dst)
                                return;
 
@@ -123,7 +165,7 @@ early_efi_write(struct console *con, const char *str, unsigned int num)
                                s++;
                        }
 
-                       early_iounmap(dst, len);
+                       early_efi_unmap(dst, len);
                }
 
                num -= count;
@@ -179,6 +221,9 @@ static __init int early_efi_setup(struct console *con, char *options)
        for (i = 0; i < (yres - efi_y) / font->height; i++)
                early_efi_scroll_up();
 
+       /* early_console_register will unset CON_BOOT in case ,keep */
+       if (!(con->flags & CON_BOOT))
+               early_efi_keep = true;
        return 0;
 }
 
index ff0174dda810fd026bfde830747d52f48ffbdb0d..a9acde72d4ed9844b62c0ce87a5d441f21004ced 100644 (file)
@@ -75,7 +75,7 @@ static int xo1_power_state_enter(suspend_state_t pm_state)
        return 0;
 }
 
-asmlinkage int xo1_do_sleep(u8 sleep_state)
+asmlinkage __visible int xo1_do_sleep(u8 sleep_state)
 {
        void *pgd_addr = __va(read_cr3());
 
index 304fca20d96ee3e1540d7045a9e0e25118c240b0..35e2bb6c0f372d1ff6f91a6078efa339b25efd78 100644 (file)
@@ -23,7 +23,7 @@
 extern __visible const void __nosave_begin, __nosave_end;
 
 /* Defined in hibernate_asm_64.S */
-extern asmlinkage int restore_image(void);
+extern asmlinkage __visible int restore_image(void);
 
 /*
  * Address to jump to in the last phase of restore in order to get to the image
index 00348980a3a64a49180be23bda3517d314c6bf81..e1f220e3ca6899af1d542ce7d22903e961754c7c 100644 (file)
@@ -39,6 +39,7 @@
 #ifdef CONFIG_X86_64
 #define vdso_enabled                   sysctl_vsyscall32
 #define arch_setup_additional_pages    syscall32_setup_pages
+extern int sysctl_ldt16;
 #endif
 
 /*
@@ -249,6 +250,13 @@ static struct ctl_table abi_table2[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec
        },
+       {
+               .procname       = "ldt16",
+               .data           = &sysctl_ldt16,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec
+       },
        {}
 };
 
index 201d09a7c46bbae56a21d15e56e222d67163f5ff..f17b29210ac4f6ddf16805e453270061bc234caf 100644 (file)
@@ -1339,6 +1339,7 @@ xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
 
 static struct notifier_block xen_panic_block = {
        .notifier_call= xen_panic_event,
+       .priority = INT_MIN
 };
 
 int xen_panic_handler_init(void)
@@ -1515,7 +1516,7 @@ static void __init xen_pvh_early_guest_init(void)
 }
 
 /* First C function to be called on Xen boot */
-asmlinkage void __init xen_start_kernel(void)
+asmlinkage __visible void __init xen_start_kernel(void)
 {
        struct physdev_set_iopl set_iopl;
        int rc;
index 08f763de26fe4132d7e6dcf0a7b50a660af76319..a1207cb6472a90ce9e57deeb1bd63eb8ebd74c4d 100644 (file)
@@ -23,7 +23,7 @@ void xen_force_evtchn_callback(void)
        (void)HYPERVISOR_xen_version(0, NULL);
 }
 
-asmlinkage unsigned long xen_save_fl(void)
+asmlinkage __visible unsigned long xen_save_fl(void)
 {
        struct vcpu_info *vcpu;
        unsigned long flags;
@@ -63,7 +63,7 @@ __visible void xen_restore_fl(unsigned long flags)
 }
 PV_CALLEE_SAVE_REGS_THUNK(xen_restore_fl);
 
-asmlinkage void xen_irq_disable(void)
+asmlinkage __visible void xen_irq_disable(void)
 {
        /* There's a one instruction preempt window here.  We need to
           make sure we're don't switch CPUs between getting the vcpu
@@ -74,7 +74,7 @@ asmlinkage void xen_irq_disable(void)
 }
 PV_CALLEE_SAVE_REGS_THUNK(xen_irq_disable);
 
-asmlinkage void xen_irq_enable(void)
+asmlinkage __visible void xen_irq_enable(void)
 {
        struct vcpu_info *vcpu;
 
index 86e02eabb640bd889c94ccb563181cd30690ceeb..6f6e15d284667640def0bd65bcc55e9836ecfd01 100644 (file)
@@ -2510,6 +2510,95 @@ void __init xen_hvm_init_mmu_ops(void)
 }
 #endif
 
+#ifdef CONFIG_XEN_PVH
+/*
+ * Map foreign gfn (fgfn), to local pfn (lpfn). This for the user
+ * space creating new guest on pvh dom0 and needing to map domU pages.
+ */
+static int xlate_add_to_p2m(unsigned long lpfn, unsigned long fgfn,
+                           unsigned int domid)
+{
+       int rc, err = 0;
+       xen_pfn_t gpfn = lpfn;
+       xen_ulong_t idx = fgfn;
+
+       struct xen_add_to_physmap_range xatp = {
+               .domid = DOMID_SELF,
+               .foreign_domid = domid,
+               .size = 1,
+               .space = XENMAPSPACE_gmfn_foreign,
+       };
+       set_xen_guest_handle(xatp.idxs, &idx);
+       set_xen_guest_handle(xatp.gpfns, &gpfn);
+       set_xen_guest_handle(xatp.errs, &err);
+
+       rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap_range, &xatp);
+       if (rc < 0)
+               return rc;
+       return err;
+}
+
+static int xlate_remove_from_p2m(unsigned long spfn, int count)
+{
+       struct xen_remove_from_physmap xrp;
+       int i, rc;
+
+       for (i = 0; i < count; i++) {
+               xrp.domid = DOMID_SELF;
+               xrp.gpfn = spfn+i;
+               rc = HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &xrp);
+               if (rc)
+                       break;
+       }
+       return rc;
+}
+
+struct xlate_remap_data {
+       unsigned long fgfn; /* foreign domain's gfn */
+       pgprot_t prot;
+       domid_t  domid;
+       int index;
+       struct page **pages;
+};
+
+static int xlate_map_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr,
+                           void *data)
+{
+       int rc;
+       struct xlate_remap_data *remap = data;
+       unsigned long pfn = page_to_pfn(remap->pages[remap->index++]);
+       pte_t pteval = pte_mkspecial(pfn_pte(pfn, remap->prot));
+
+       rc = xlate_add_to_p2m(pfn, remap->fgfn, remap->domid);
+       if (rc)
+               return rc;
+       native_set_pte(ptep, pteval);
+
+       return 0;
+}
+
+static int xlate_remap_gfn_range(struct vm_area_struct *vma,
+                                unsigned long addr, unsigned long mfn,
+                                int nr, pgprot_t prot, unsigned domid,
+                                struct page **pages)
+{
+       int err;
+       struct xlate_remap_data pvhdata;
+
+       BUG_ON(!pages);
+
+       pvhdata.fgfn = mfn;
+       pvhdata.prot = prot;
+       pvhdata.domid = domid;
+       pvhdata.index = 0;
+       pvhdata.pages = pages;
+       err = apply_to_page_range(vma->vm_mm, addr, nr << PAGE_SHIFT,
+                                 xlate_map_pte_fn, &pvhdata);
+       flush_tlb_all();
+       return err;
+}
+#endif
+
 #define REMAP_BATCH_SIZE 16
 
 struct remap_data {
@@ -2522,7 +2611,7 @@ static int remap_area_mfn_pte_fn(pte_t *ptep, pgtable_t token,
                                 unsigned long addr, void *data)
 {
        struct remap_data *rmd = data;
-       pte_t pte = pte_mkspecial(pfn_pte(rmd->mfn++, rmd->prot));
+       pte_t pte = pte_mkspecial(mfn_pte(rmd->mfn++, rmd->prot));
 
        rmd->mmu_update->ptr = virt_to_machine(ptep).maddr;
        rmd->mmu_update->val = pte_val_ma(pte);
@@ -2544,13 +2633,18 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
        unsigned long range;
        int err = 0;
 
-       if (xen_feature(XENFEAT_auto_translated_physmap))
-               return -EINVAL;
-
-       prot = __pgprot(pgprot_val(prot) | _PAGE_IOMAP);
-
        BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO)));
 
+       if (xen_feature(XENFEAT_auto_translated_physmap)) {
+#ifdef CONFIG_XEN_PVH
+               /* We need to update the local page tables and the xen HAP */
+               return xlate_remap_gfn_range(vma, addr, mfn, nr, prot,
+                                            domid, pages);
+#else
+               return -EINVAL;
+#endif
+        }
+
        rmd.mfn = mfn;
        rmd.prot = prot;
 
@@ -2588,6 +2682,25 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
        if (!pages || !xen_feature(XENFEAT_auto_translated_physmap))
                return 0;
 
+#ifdef CONFIG_XEN_PVH
+       while (numpgs--) {
+               /*
+                * The mmu has already cleaned up the process mmu
+                * resources at this point (lookup_address will return
+                * NULL).
+                */
+               unsigned long pfn = page_to_pfn(pages[numpgs]);
+
+               xlate_remove_from_p2m(pfn, 1);
+       }
+       /*
+        * We don't need to flush tlbs because as part of
+        * xlate_remove_from_p2m, the hypervisor will do tlb flushes
+        * after removing the p2m entries from the EPT/NPT
+        */
+       return 0;
+#else
        return -EINVAL;
+#endif
 }
 EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range);
index 85e5d78c9874847d41edbfbe2e4fcb9df46a4d75..9bb3d82ffec8f8de8c0fb4f9db920ea260543171 100644 (file)
@@ -36,7 +36,7 @@
  *  pfn_to_mfn(0xc0000)=0xc0000
  *
  * The benefit of this is, that we can assume for non-RAM regions (think
- * PCI BARs, or ACPI spaces), we can create mappings easily b/c we
+ * PCI BARs, or ACPI spaces), we can create mappings easily because we
  * get the PFN value to match the MFN.
  *
  * For this to work efficiently we have one new page p2m_identity and
@@ -60,7 +60,7 @@
  * There is also a digram of the P2M at the end that can help.
  * Imagine your E820 looking as so:
  *
- *                    1GB                                           2GB
+ *                    1GB                                           2GB    4GB
  * /-------------------+---------\/----\         /----------\    /---+-----\
  * | System RAM        | Sys RAM ||ACPI|         | reserved |    | Sys RAM |
  * \-------------------+---------/\----/         \----------/    \---+-----/
@@ -77,9 +77,8 @@
  * of the PFN and the end PFN (263424 and 512256 respectively). The first step
  * is to reserve_brk a top leaf page if the p2m[1] is missing. The top leaf page
  * covers 512^2 of page estate (1GB) and in case the start or end PFN is not
- * aligned on 512^2*PAGE_SIZE (1GB) we loop on aligned 1GB PFNs from start pfn
- * to end pfn.  We reserve_brk top leaf pages if they are missing (means they
- * point to p2m_mid_missing).
+ * aligned on 512^2*PAGE_SIZE (1GB) we reserve_brk new middle and leaf pages as
+ * required to split any existing p2m_mid_missing middle pages.
  *
  * With the E820 example above, 263424 is not 1GB aligned so we allocate a
  * reserve_brk page which will cover the PFNs estate from 0x40000 to 0x80000.
@@ -88,7 +87,7 @@
  * Next stage is to determine if we need to do a more granular boundary check
  * on the 4MB (or 2MB depending on architecture) off the start and end pfn's.
  * We check if the start pfn and end pfn violate that boundary check, and if
- * so reserve_brk a middle (p2m[x][y]) leaf page. This way we have a much finer
+ * so reserve_brk a (p2m[x][y]) leaf page. This way we have a much finer
  * granularity of setting which PFNs are missing and which ones are identity.
  * In our example 263424 and 512256 both fail the check so we reserve_brk two
  * pages. Populate them with INVALID_P2M_ENTRY (so they both have "missing"
  *
  * The next step is to walk from the start pfn to the end pfn setting
  * the IDENTITY_FRAME_BIT on each PFN. This is done in set_phys_range_identity.
- * If we find that the middle leaf is pointing to p2m_missing we can swap it
- * over to p2m_identity - this way covering 4MB (or 2MB) PFN space.  At this
- * point we do not need to worry about boundary aligment (so no need to
+ * If we find that the middle entry is pointing to p2m_missing we can swap it
+ * over to p2m_identity - this way covering 4MB (or 2MB) PFN space (and
+ * similarly swapping p2m_mid_missing for p2m_mid_identity for larger regions).
+ * At this point we do not need to worry about boundary aligment (so no need to
  * reserve_brk a middle page, figure out which PFNs are "missing" and which
  * ones are identity), as that has been done earlier.  If we find that the
  * middle leaf is not occupied by p2m_identity or p2m_missing, we dereference
  * considered missing). In our case, p2m[1][2][0->255] and p2m[1][488][257->511]
  * contain the INVALID_P2M_ENTRY value and are considered "missing."
  *
+ * Finally, the region beyond the end of of the E820 (4 GB in this example)
+ * is set to be identity (in case there are MMIO regions placed here).
+ *
  * This is what the p2m ends up looking (for the E820 above) with this
  * fabulous drawing:
  *
  *  |-----|    \                      | [p2m_identity]+\\    | ....            |
  *  |  2  |--\  \-------------------->|  ...          | \\   \----------------/
  *  |-----|   \                       \---------------/  \\
- *  |  3  |\   \                                          \\  p2m_identity
- *  |-----| \   \-------------------->/---------------\   /-----------------\
- *  | ..  +->+                        | [p2m_identity]+-->| ~0, ~0, ~0, ... |
- *  \-----/ /                         | [p2m_identity]+-->| ..., ~0         |
- *         / /---------------\        | ....          |   \-----------------/
- *        /  | IDENTITY[@0]  |      /-+-[x], ~0, ~0.. |
- *       /   | IDENTITY[@256]|<----/  \---------------/
- *      /    | ~0, ~0, ....  |
- *     |     \---------------/
- *     |
- *   p2m_mid_missing           p2m_missing
- * /-----------------\     /------------\
- * | [p2m_missing]   +---->| ~0, ~0, ~0 |
- * | [p2m_missing]   +---->| ..., ~0    |
- * \-----------------/     \------------/
+ *  |  3  |-\  \                                          \\  p2m_identity [1]
+ *  |-----|  \  \-------------------->/---------------\   /-----------------\
+ *  | ..  |\  |                       | [p2m_identity]+-->| ~0, ~0, ~0, ... |
+ *  \-----/ | |                       | [p2m_identity]+-->| ..., ~0         |
+ *          | |                       | ....          |   \-----------------/
+ *          | |                       +-[x], ~0, ~0.. +\
+ *          | |                       \---------------/ \
+ *          | |                                          \-> /---------------\
+ *          | V  p2m_mid_missing       p2m_missing           | IDENTITY[@0]  |
+ *          | /-----------------\     /------------\         | IDENTITY[@256]|
+ *          | | [p2m_missing]   +---->| ~0, ~0, ...|         | ~0, ~0, ....  |
+ *          | | [p2m_missing]   +---->| ..., ~0    |         \---------------/
+ *          | | ...             |     \------------/
+ *          | \-----------------/
+ *          |
+ *          |     p2m_mid_identity
+ *          |   /-----------------\
+ *          \-->| [p2m_identity]  +---->[1]
+ *              | [p2m_identity]  +---->[1]
+ *              | ...             |
+ *              \-----------------/
  *
  * where ~0 is INVALID_P2M_ENTRY. IDENTITY is (PFN | IDENTITY_BIT)
  */
@@ -187,13 +196,15 @@ static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE);
 static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE);
 
 static RESERVE_BRK_ARRAY(unsigned long, p2m_identity, P2M_PER_PAGE);
+static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_identity, P2M_MID_PER_PAGE);
+static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_identity_mfn, P2M_MID_PER_PAGE);
 
 RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
 RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
 
 /* We might hit two boundary violations at the start and end, at max each
  * boundary violation will require three middle nodes. */
-RESERVE_BRK(p2m_mid_identity, PAGE_SIZE * 2 * 3);
+RESERVE_BRK(p2m_mid_extra, PAGE_SIZE * 2 * 3);
 
 /* When we populate back during bootup, the amount of pages can vary. The
  * max we have is seen is 395979, but that does not mean it can't be more.
@@ -242,20 +253,20 @@ static void p2m_top_mfn_p_init(unsigned long **top)
                top[i] = p2m_mid_missing_mfn;
 }
 
-static void p2m_mid_init(unsigned long **mid)
+static void p2m_mid_init(unsigned long **mid, unsigned long *leaf)
 {
        unsigned i;
 
        for (i = 0; i < P2M_MID_PER_PAGE; i++)
-               mid[i] = p2m_missing;
+               mid[i] = leaf;
 }
 
-static void p2m_mid_mfn_init(unsigned long *mid)
+static void p2m_mid_mfn_init(unsigned long *mid, unsigned long *leaf)
 {
        unsigned i;
 
        for (i = 0; i < P2M_MID_PER_PAGE; i++)
-               mid[i] = virt_to_mfn(p2m_missing);
+               mid[i] = virt_to_mfn(leaf);
 }
 
 static void p2m_init(unsigned long *p2m)
@@ -286,7 +297,9 @@ void __ref xen_build_mfn_list_list(void)
        /* Pre-initialize p2m_top_mfn to be completely missing */
        if (p2m_top_mfn == NULL) {
                p2m_mid_missing_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
-               p2m_mid_mfn_init(p2m_mid_missing_mfn);
+               p2m_mid_mfn_init(p2m_mid_missing_mfn, p2m_missing);
+               p2m_mid_identity_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
+               p2m_mid_mfn_init(p2m_mid_identity_mfn, p2m_identity);
 
                p2m_top_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
                p2m_top_mfn_p_init(p2m_top_mfn_p);
@@ -295,7 +308,8 @@ void __ref xen_build_mfn_list_list(void)
                p2m_top_mfn_init(p2m_top_mfn);
        } else {
                /* Reinitialise, mfn's all change after migration */
-               p2m_mid_mfn_init(p2m_mid_missing_mfn);
+               p2m_mid_mfn_init(p2m_mid_missing_mfn, p2m_missing);
+               p2m_mid_mfn_init(p2m_mid_identity_mfn, p2m_identity);
        }
 
        for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += P2M_PER_PAGE) {
@@ -327,7 +341,7 @@ void __ref xen_build_mfn_list_list(void)
                         * it too late.
                         */
                        mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
-                       p2m_mid_mfn_init(mid_mfn_p);
+                       p2m_mid_mfn_init(mid_mfn_p, p2m_missing);
 
                        p2m_top_mfn_p[topidx] = mid_mfn_p;
                }
@@ -365,16 +379,17 @@ void __init xen_build_dynamic_phys_to_machine(void)
 
        p2m_missing = extend_brk(PAGE_SIZE, PAGE_SIZE);
        p2m_init(p2m_missing);
+       p2m_identity = extend_brk(PAGE_SIZE, PAGE_SIZE);
+       p2m_init(p2m_identity);
 
        p2m_mid_missing = extend_brk(PAGE_SIZE, PAGE_SIZE);
-       p2m_mid_init(p2m_mid_missing);
+       p2m_mid_init(p2m_mid_missing, p2m_missing);
+       p2m_mid_identity = extend_brk(PAGE_SIZE, PAGE_SIZE);
+       p2m_mid_init(p2m_mid_identity, p2m_identity);
 
        p2m_top = extend_brk(PAGE_SIZE, PAGE_SIZE);
        p2m_top_init(p2m_top);
 
-       p2m_identity = extend_brk(PAGE_SIZE, PAGE_SIZE);
-       p2m_init(p2m_identity);
-
        /*
         * The domain builder gives us a pre-constructed p2m array in
         * mfn_list for all the pages initially given to us, so we just
@@ -386,7 +401,7 @@ void __init xen_build_dynamic_phys_to_machine(void)
 
                if (p2m_top[topidx] == p2m_mid_missing) {
                        unsigned long **mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
-                       p2m_mid_init(mid);
+                       p2m_mid_init(mid, p2m_missing);
 
                        p2m_top[topidx] = mid;
                }
@@ -492,7 +507,7 @@ unsigned long get_phys_to_machine(unsigned long pfn)
        unsigned topidx, mididx, idx;
 
        if (unlikely(pfn >= MAX_P2M_PFN))
-               return INVALID_P2M_ENTRY;
+               return IDENTITY_FRAME(pfn);
 
        topidx = p2m_top_index(pfn);
        mididx = p2m_mid_index(pfn);
@@ -545,7 +560,7 @@ static bool alloc_p2m(unsigned long pfn)
                if (!mid)
                        return false;
 
-               p2m_mid_init(mid);
+               p2m_mid_init(mid, p2m_missing);
 
                if (cmpxchg(top_p, p2m_mid_missing, mid) != p2m_mid_missing)
                        free_p2m_page(mid);
@@ -565,7 +580,7 @@ static bool alloc_p2m(unsigned long pfn)
                if (!mid_mfn)
                        return false;
 
-               p2m_mid_mfn_init(mid_mfn);
+               p2m_mid_mfn_init(mid_mfn, p2m_missing);
 
                missing_mfn = virt_to_mfn(p2m_mid_missing_mfn);
                mid_mfn_mfn = virt_to_mfn(mid_mfn);
@@ -596,7 +611,7 @@ static bool alloc_p2m(unsigned long pfn)
        return true;
 }
 
-static bool __init early_alloc_p2m_middle(unsigned long pfn, bool check_boundary)
+static bool __init early_alloc_p2m(unsigned long pfn, bool check_boundary)
 {
        unsigned topidx, mididx, idx;
        unsigned long *p2m;
@@ -638,7 +653,7 @@ static bool __init early_alloc_p2m_middle(unsigned long pfn, bool check_boundary
        return true;
 }
 
-static bool __init early_alloc_p2m(unsigned long pfn)
+static bool __init early_alloc_p2m_middle(unsigned long pfn)
 {
        unsigned topidx = p2m_top_index(pfn);
        unsigned long *mid_mfn_p;
@@ -649,7 +664,7 @@ static bool __init early_alloc_p2m(unsigned long pfn)
        if (mid == p2m_mid_missing) {
                mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
 
-               p2m_mid_init(mid);
+               p2m_mid_init(mid, p2m_missing);
 
                p2m_top[topidx] = mid;
 
@@ -658,12 +673,12 @@ static bool __init early_alloc_p2m(unsigned long pfn)
        /* And the save/restore P2M tables.. */
        if (mid_mfn_p == p2m_mid_missing_mfn) {
                mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
-               p2m_mid_mfn_init(mid_mfn_p);
+               p2m_mid_mfn_init(mid_mfn_p, p2m_missing);
 
                p2m_top_mfn_p[topidx] = mid_mfn_p;
                p2m_top_mfn[topidx] = virt_to_mfn(mid_mfn_p);
                /* Note: we don't set mid_mfn_p[midix] here,
-                * look in early_alloc_p2m_middle */
+                * look in early_alloc_p2m() */
        }
        return true;
 }
@@ -739,7 +754,7 @@ found:
 
        /* This shouldn't happen */
        if (WARN_ON(p2m_top[topidx] == p2m_mid_missing))
-               early_alloc_p2m(set_pfn);
+               early_alloc_p2m_middle(set_pfn);
 
        if (WARN_ON(p2m_top[topidx][mididx] != p2m_missing))
                return false;
@@ -754,13 +769,13 @@ found:
 bool __init early_set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 {
        if (unlikely(!__set_phys_to_machine(pfn, mfn)))  {
-               if (!early_alloc_p2m(pfn))
+               if (!early_alloc_p2m_middle(pfn))
                        return false;
 
                if (early_can_reuse_p2m_middle(pfn, mfn))
                        return __set_phys_to_machine(pfn, mfn);
 
-               if (!early_alloc_p2m_middle(pfn, false /* boundary crossover OK!*/))
+               if (!early_alloc_p2m(pfn, false /* boundary crossover OK!*/))
                        return false;
 
                if (!__set_phys_to_machine(pfn, mfn))
@@ -769,12 +784,30 @@ bool __init early_set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 
        return true;
 }
+
+static void __init early_split_p2m(unsigned long pfn)
+{
+       unsigned long mididx, idx;
+
+       mididx = p2m_mid_index(pfn);
+       idx = p2m_index(pfn);
+
+       /*
+        * Allocate new middle and leaf pages if this pfn lies in the
+        * middle of one.
+        */
+       if (mididx || idx)
+               early_alloc_p2m_middle(pfn);
+       if (idx)
+               early_alloc_p2m(pfn, false);
+}
+
 unsigned long __init set_phys_range_identity(unsigned long pfn_s,
                                      unsigned long pfn_e)
 {
        unsigned long pfn;
 
-       if (unlikely(pfn_s >= MAX_P2M_PFN || pfn_e >= MAX_P2M_PFN))
+       if (unlikely(pfn_s >= MAX_P2M_PFN))
                return 0;
 
        if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
@@ -783,19 +816,30 @@ unsigned long __init set_phys_range_identity(unsigned long pfn_s,
        if (pfn_s > pfn_e)
                return 0;
 
-       for (pfn = (pfn_s & ~(P2M_MID_PER_PAGE * P2M_PER_PAGE - 1));
-               pfn < ALIGN(pfn_e, (P2M_MID_PER_PAGE * P2M_PER_PAGE));
-               pfn += P2M_MID_PER_PAGE * P2M_PER_PAGE)
-       {
-               WARN_ON(!early_alloc_p2m(pfn));
-       }
+       if (pfn_e > MAX_P2M_PFN)
+               pfn_e = MAX_P2M_PFN;
 
-       early_alloc_p2m_middle(pfn_s, true);
-       early_alloc_p2m_middle(pfn_e, true);
+       early_split_p2m(pfn_s);
+       early_split_p2m(pfn_e);
+
+       for (pfn = pfn_s; pfn < pfn_e;) {
+               unsigned topidx = p2m_top_index(pfn);
+               unsigned mididx = p2m_mid_index(pfn);
 
-       for (pfn = pfn_s; pfn < pfn_e; pfn++)
                if (!__set_phys_to_machine(pfn, IDENTITY_FRAME(pfn)))
                        break;
+               pfn++;
+
+               /*
+                * If the PFN was set to a middle or leaf identity
+                * page the remainder must also be identity, so skip
+                * ahead to the next middle or leaf entry.
+                */
+               if (p2m_top[topidx] == p2m_mid_identity)
+                       pfn = ALIGN(pfn, P2M_MID_PER_PAGE * P2M_PER_PAGE);
+               else if (p2m_top[topidx][mididx] == p2m_identity)
+                       pfn = ALIGN(pfn, P2M_PER_PAGE);
+       }
 
        if (!WARN((pfn - pfn_s) != (pfn_e - pfn_s),
                "Identity mapping failed. We are %ld short of 1-1 mappings!\n",
@@ -825,8 +869,22 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 
        /* For sparse holes were the p2m leaf has real PFN along with
         * PCI holes, stick in the PFN as the MFN value.
+        *
+        * set_phys_range_identity() will have allocated new middle
+        * and leaf pages as required so an existing p2m_mid_missing
+        * or p2m_missing mean that whole range will be identity so
+        * these can be switched to p2m_mid_identity or p2m_identity.
         */
        if (mfn != INVALID_P2M_ENTRY && (mfn & IDENTITY_FRAME_BIT)) {
+               if (p2m_top[topidx] == p2m_mid_identity)
+                       return true;
+
+               if (p2m_top[topidx] == p2m_mid_missing) {
+                       WARN_ON(cmpxchg(&p2m_top[topidx], p2m_mid_missing,
+                                       p2m_mid_identity) != p2m_mid_missing);
+                       return true;
+               }
+
                if (p2m_top[topidx][mididx] == p2m_identity)
                        return true;
 
index 0982233b9b8433a97d6905de4aad3369c6f4c0a5..210426a26cc0d92f9722ec297466bccbbf232982 100644 (file)
@@ -89,10 +89,10 @@ static void __init xen_add_extra_mem(u64 start, u64 size)
        for (pfn = PFN_DOWN(start); pfn < xen_max_p2m_pfn; pfn++) {
                unsigned long mfn = pfn_to_mfn(pfn);
 
-               if (WARN(mfn == pfn, "Trying to over-write 1-1 mapping (pfn: %lx)\n", pfn))
+               if (WARN_ONCE(mfn == pfn, "Trying to over-write 1-1 mapping (pfn: %lx)\n", pfn))
                        continue;
-               WARN(mfn != INVALID_P2M_ENTRY, "Trying to remove %lx which has %lx mfn!\n",
-                       pfn, mfn);
+               WARN_ONCE(mfn != INVALID_P2M_ENTRY, "Trying to remove %lx which has %lx mfn!\n",
+                         pfn, mfn);
 
                __set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
        }
@@ -468,6 +468,15 @@ char * __init xen_memory_setup(void)
                        i++;
        }
 
+       /*
+        * Set the rest as identity mapped, in case PCI BARs are
+        * located here.
+        *
+        * PFNs above MAX_P2M_PFN are considered identity mapped as
+        * well.
+        */
+       set_phys_range_identity(map[i-1].addr / PAGE_SIZE, ~0ul);
+
        /*
         * In domU, the ISA region is normal, usable memory, but we
         * reserve ISA memory anyway because too many things poke
index 45329c8c226e4c4070f16a791b300265a0bf472b..c4df9dbd63b7c81f70c624c417d8362b85d3d34e 100644 (file)
 #include "xen-ops.h"
 #include "mmu.h"
 
-void xen_arch_pre_suspend(void)
+static void xen_pv_pre_suspend(void)
 {
+       xen_mm_pin_all();
+
        xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
        xen_start_info->console.domU.mfn =
                mfn_to_pfn(xen_start_info->console.domU.mfn);
@@ -26,7 +28,7 @@ void xen_arch_pre_suspend(void)
                BUG();
 }
 
-void xen_arch_hvm_post_suspend(int suspend_cancelled)
+static void xen_hvm_post_suspend(int suspend_cancelled)
 {
 #ifdef CONFIG_XEN_PVHVM
        int cpu;
@@ -41,7 +43,7 @@ void xen_arch_hvm_post_suspend(int suspend_cancelled)
 #endif
 }
 
-void xen_arch_post_suspend(int suspend_cancelled)
+static void xen_pv_post_suspend(int suspend_cancelled)
 {
        xen_build_mfn_list_list();
 
@@ -60,6 +62,21 @@ void xen_arch_post_suspend(int suspend_cancelled)
                xen_vcpu_restore();
        }
 
+       xen_mm_unpin_all();
+}
+
+void xen_arch_pre_suspend(void)
+{
+    if (xen_pv_domain())
+        xen_pv_pre_suspend();
+}
+
+void xen_arch_post_suspend(int cancelled)
+{
+    if (xen_pv_domain())
+        xen_pv_post_suspend(cancelled);
+    else
+        xen_hvm_post_suspend(cancelled);
 }
 
 static void xen_vcpu_notify_restore(void *data)
index 1cb6f4c373002b39971d08cdfc71f3add935daf3..c834d4b231f08d65319448ef8436ff1ec99d364a 100644 (file)
@@ -31,6 +31,8 @@ void xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn);
 void xen_reserve_top(void);
 extern unsigned long xen_max_p2m_pfn;
 
+void xen_mm_pin_all(void);
+void xen_mm_unpin_all(void);
 void xen_set_pat(u64);
 
 char * __init xen_memory_setup(void);
index 02d6d29a63c13716168c0a68b4bdfe55c71ef9b0..3a617af60d465196bb894cebdc4042ccd4e4a92f 100644 (file)
@@ -14,6 +14,7 @@ config XTENSA
        select GENERIC_PCI_IOMAP
        select ARCH_WANT_IPC_PARSE_VERSION
        select ARCH_WANT_OPTIONAL_GPIOLIB
+       select BUILDTIME_EXTABLE_SORT
        select CLONE_BACKWARDS
        select IRQ_DOMAIN
        select HAVE_OPROFILE
@@ -189,6 +190,24 @@ config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
 
          If in doubt, say Y.
 
+config HIGHMEM
+       bool "High Memory Support"
+       help
+         Linux can use the full amount of RAM in the system by
+         default. However, the default MMUv2 setup only maps the
+         lowermost 128 MB of memory linearly to the areas starting
+         at 0xd0000000 (cached) and 0xd8000000 (uncached).
+         When there are more than 128 MB memory in the system not
+         all of it can be "permanently mapped" by the kernel.
+         The physical memory that's not permanently mapped is called
+         "high memory".
+
+         If you are compiling a kernel which will never run on a
+         machine with more than 128 MB total physical RAM, answer
+         N here.
+
+         If unsure, say Y.
+
 endmenu
 
 config XTENSA_CALIBRATE_CCOUNT
@@ -224,7 +243,6 @@ choice
 
 config XTENSA_PLATFORM_ISS
        bool "ISS"
-       depends on TTY
        select XTENSA_CALIBRATE_CCOUNT
        select SERIAL_CONSOLE
        help
diff --git a/arch/xtensa/boot/dts/kc705.dts b/arch/xtensa/boot/dts/kc705.dts
new file mode 100644 (file)
index 0000000..742a347
--- /dev/null
@@ -0,0 +1,11 @@
+/dts-v1/;
+/include/ "xtfpga.dtsi"
+/include/ "xtfpga-flash-128m.dtsi"
+
+/ {
+       compatible = "cdns,xtensa-kc705";
+       memory@0 {
+               device_type = "memory";
+               reg = <0x00000000 0x08000000>;
+       };
+};
diff --git a/arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi b/arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi
new file mode 100644 (file)
index 0000000..d3a88e0
--- /dev/null
@@ -0,0 +1,28 @@
+/ {
+       soc {
+               flash: flash@00000000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "cfi-flash";
+                       reg = <0x00000000 0x08000000>;
+                       bank-width = <2>;
+                       device-width = <2>;
+                       partition@0x0 {
+                               label = "data";
+                               reg = <0x00000000 0x06000000>;
+                       };
+                       partition@0x6000000 {
+                               label = "boot loader area";
+                               reg = <0x06000000 0x00800000>;
+                       };
+                       partition@0x6800000 {
+                               label = "kernel image";
+                               reg = <0x06800000 0x017e0000>;
+                       };
+                       partition@0x7fe0000 {
+                               label = "boot environment";
+                               reg = <0x07fe0000 0x00020000>;
+                       };
+               };
+        };
+};
index e5703c7beeb6dad04d2006929984b0fd8a7c3289..1d97203c18e7f787b5696b4468e4901c9b88fcbb 100644 (file)
@@ -1,26 +1,28 @@
 / {
-       flash: flash@f8000000 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               compatible = "cfi-flash";
-               reg = <0xf8000000 0x01000000>;
-               bank-width = <2>;
-               device-width = <2>;
-               partition@0x0 {
-                       label = "boot loader area";
-                       reg = <0x00000000 0x00400000>;
+       soc {
+               flash: flash@08000000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "cfi-flash";
+                       reg = <0x08000000 0x01000000>;
+                       bank-width = <2>;
+                       device-width = <2>;
+                       partition@0x0 {
+                               label = "boot loader area";
+                               reg = <0x00000000 0x00400000>;
+                       };
+                       partition@0x400000 {
+                               label = "kernel image";
+                               reg = <0x00400000 0x00600000>;
+                       };
+                       partition@0xa00000 {
+                               label = "data";
+                               reg = <0x00a00000 0x005e0000>;
+                       };
+                       partition@0xfe0000 {
+                               label = "boot environment";
+                               reg = <0x00fe0000 0x00020000>;
+                       };
                };
-               partition@0x400000 {
-                       label = "kernel image";
-                       reg = <0x00400000 0x00600000>;
-               };
-               partition@0xa00000 {
-                       label = "data";
-                       reg = <0x00a00000 0x005e0000>;
-               };
-               partition@0xfe0000 {
-                       label = "boot environment";
-                       reg = <0x00fe0000 0x00020000>;
-               };
-        };
+       };
 };
index 6f9c10d6b689a9696d17296025a21a1167322fbc..d1c621ca8be10cba5565fa9ce1e7b82cabaef973 100644 (file)
@@ -1,18 +1,20 @@
 / {
-       flash: flash@f8000000 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               compatible = "cfi-flash";
-               reg = <0xf8000000 0x00400000>;
-               bank-width = <2>;
-               device-width = <2>;
-               partition@0x0 {
-                       label = "boot loader area";
-                       reg = <0x00000000 0x003f0000>;
+       soc {
+               flash: flash@08000000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "cfi-flash";
+                       reg = <0x08000000 0x00400000>;
+                       bank-width = <2>;
+                       device-width = <2>;
+                       partition@0x0 {
+                               label = "boot loader area";
+                               reg = <0x00000000 0x003f0000>;
+                       };
+                       partition@0x3f0000 {
+                               label = "boot environment";
+                               reg = <0x003f0000 0x00010000>;
+                       };
                };
-               partition@0x3f0000 {
-                       label = "boot environment";
-                       reg = <0x003f0000 0x00010000>;
-               };
-        };
+       };
 };
index e7370b11348e8d06c113d420704664740dbdec9b..dec9178840f695f0bcdd1de3cd5b17339fce8627 100644 (file)
                };
        };
 
-       serial0: serial@fd050020 {
-               device_type = "serial";
-               compatible = "ns16550a";
-               no-loopback-test;
-               reg = <0xfd050020 0x20>;
-               reg-shift = <2>;
-               interrupts = <0 1>; /* external irq 0 */
-               clocks = <&osc>;
-       };
+       soc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "simple-bus";
+               ranges = <0x00000000 0xf0000000 0x10000000>;
 
-       enet0: ethoc@fd030000 {
-               compatible = "opencores,ethoc";
-               reg = <0xfd030000 0x4000 0xfd800000 0x4000>;
-               interrupts = <1 1>; /* external irq 1 */
-               local-mac-address = [00 50 c2 13 6f 00];
-               clocks = <&osc>;
+               serial0: serial@0d050020 {
+                       device_type = "serial";
+                       compatible = "ns16550a";
+                       no-loopback-test;
+                       reg = <0x0d050020 0x20>;
+                       reg-shift = <2>;
+                       interrupts = <0 1>; /* external irq 0 */
+                       clocks = <&osc>;
+               };
+
+               enet0: ethoc@0d030000 {
+                       compatible = "opencores,ethoc";
+                       reg = <0x0d030000 0x4000 0x0d800000 0x4000>;
+                       interrupts = <1 1>; /* external irq 1 */
+                       local-mac-address = [00 50 c2 13 6f 00];
+                       clocks = <&osc>;
+               };
        };
 };
index 23392c5630ce9939b04bae3ff6de4fd67417852a..892aab399ac873c885953e24430a3bc741aca6ed 100644 (file)
@@ -37,23 +37,14 @@ typedef struct bp_tag {
        unsigned long data[0];  /* data */
 } bp_tag_t;
 
-typedef struct meminfo {
+struct bp_meminfo {
        unsigned long type;
        unsigned long start;
        unsigned long end;
-} meminfo_t;
-
-#define SYSMEM_BANKS_MAX 5
+};
 
 #define MEMORY_TYPE_CONVENTIONAL       0x1000
 #define MEMORY_TYPE_NONE               0x2000
 
-typedef struct sysmem_info {
-       int nr_banks;
-       meminfo_t bank[SYSMEM_BANKS_MAX];
-} sysmem_info_t;
-
-extern sysmem_info_t sysmem;
-
 #endif
 #endif
diff --git a/arch/xtensa/include/asm/fixmap.h b/arch/xtensa/include/asm/fixmap.h
new file mode 100644 (file)
index 0000000..9f6c33d
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * fixmap.h: compile-time virtual memory allocation
+ *
+ * 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) 1998 Ingo Molnar
+ *
+ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+ */
+
+#ifndef _ASM_FIXMAP_H
+#define _ASM_FIXMAP_H
+
+#include <asm/pgtable.h>
+#ifdef CONFIG_HIGHMEM
+#include <linux/threads.h>
+#include <asm/kmap_types.h>
+#endif
+
+/*
+ * Here we define all the compile-time 'special' virtual
+ * addresses. The point is to have a constant address at
+ * compile time, but to set the physical address only
+ * in the boot process. We allocate these special  addresses
+ * from the end of the consistent memory region backwards.
+ * Also this lets us do fail-safe vmalloc(), we
+ * can guarantee that these special addresses and
+ * vmalloc()-ed addresses never overlap.
+ *
+ * these 'compile-time allocated' memory buffers are
+ * fixed-size 4k pages. (or larger if used with an increment
+ * higher than 1) use fixmap_set(idx,phys) to associate
+ * physical memory with fixmap indices.
+ */
+enum fixed_addresses {
+#ifdef CONFIG_HIGHMEM
+       /* reserved pte's for temporary kernel mappings */
+       FIX_KMAP_BEGIN,
+       FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1,
+#endif
+       __end_of_fixed_addresses
+};
+
+#define FIXADDR_TOP     (VMALLOC_START - PAGE_SIZE)
+#define FIXADDR_SIZE   (__end_of_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_START  ((FIXADDR_TOP - FIXADDR_SIZE) & PMD_MASK)
+
+#include <asm-generic/fixmap.h>
+
+#define kmap_get_fixmap_pte(vaddr) \
+       pte_offset_kernel( \
+               pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), \
+               (vaddr) \
+       )
+
+#endif
index 80be15124697d8e85a23859a466e97f178936010..2653ef5d55f1c9ed92d35d50f91136732334ec1b 100644 (file)
@@ -6,11 +6,54 @@
  * this archive for more details.
  *
  * Copyright (C) 2003 - 2005 Tensilica Inc.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
  */
 
 #ifndef _XTENSA_HIGHMEM_H
 #define _XTENSA_HIGHMEM_H
 
-extern void flush_cache_kmaps(void);
+#include <asm/cacheflush.h>
+#include <asm/fixmap.h>
+#include <asm/kmap_types.h>
+#include <asm/pgtable.h>
+
+#define PKMAP_BASE             (FIXADDR_START - PMD_SIZE)
+#define LAST_PKMAP             PTRS_PER_PTE
+#define LAST_PKMAP_MASK                (LAST_PKMAP - 1)
+#define PKMAP_NR(virt)         (((virt) - PKMAP_BASE) >> PAGE_SHIFT)
+#define PKMAP_ADDR(nr)         (PKMAP_BASE + ((nr) << PAGE_SHIFT))
+
+#define kmap_prot              PAGE_KERNEL
+
+extern pte_t *pkmap_page_table;
+
+void *kmap_high(struct page *page);
+void kunmap_high(struct page *page);
+
+static inline void *kmap(struct page *page)
+{
+       BUG_ON(in_interrupt());
+       if (!PageHighMem(page))
+               return page_address(page);
+       return kmap_high(page);
+}
+
+static inline void kunmap(struct page *page)
+{
+       BUG_ON(in_interrupt());
+       if (!PageHighMem(page))
+               return;
+       kunmap_high(page);
+}
+
+static inline void flush_cache_kmaps(void)
+{
+       flush_cache_all();
+}
+
+void *kmap_atomic(struct page *page);
+void __kunmap_atomic(void *kvaddr);
+
+void kmap_init(void);
 
 #endif
index 216446295ada686ccb4b454319b2b45e85d96720..4b0ca35a93b1a731bf0ce2c1db32f9fabb890fef 100644 (file)
@@ -310,6 +310,10 @@ set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval)
        update_pte(ptep, pteval);
 }
 
+static inline void set_pte(pte_t *ptep, pte_t pteval)
+{
+       update_pte(ptep, pteval);
+}
 
 static inline void
 set_pmd(pmd_t *pmdp, pmd_t pmdval)
diff --git a/arch/xtensa/include/asm/sysmem.h b/arch/xtensa/include/asm/sysmem.h
new file mode 100644 (file)
index 0000000..c015c5c
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * sysmem-related prototypes.
+ *
+ * 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) 2014 Cadence Design Systems Inc.
+ */
+
+#ifndef _XTENSA_SYSMEM_H
+#define _XTENSA_SYSMEM_H
+
+#define SYSMEM_BANKS_MAX 31
+
+struct meminfo {
+       unsigned long start;
+       unsigned long end;
+};
+
+/*
+ * Bank array is sorted by .start.
+ * Banks don't overlap and there's at least one page gap
+ * between adjacent bank entries.
+ */
+struct sysmem_info {
+       int nr_banks;
+       struct meminfo bank[SYSMEM_BANKS_MAX];
+};
+
+extern struct sysmem_info sysmem;
+
+int add_sysmem_bank(unsigned long start, unsigned long end);
+int mem_reserve(unsigned long, unsigned long, int);
+void bootmem_init(void);
+void zones_init(void);
+
+#endif /* _XTENSA_SYSMEM_H */
index fc34274ce41bc81b3ddaa167fe887179f04c8ad7..06875feb27c28ebb870820706dc286cd9740f1ce 100644 (file)
@@ -36,6 +36,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma,
                unsigned long page);
 void local_flush_tlb_range(struct vm_area_struct *vma,
                unsigned long start, unsigned long end);
+void local_flush_tlb_kernel_range(unsigned long start, unsigned long end);
 
 #ifdef CONFIG_SMP
 
@@ -44,12 +45,7 @@ void flush_tlb_mm(struct mm_struct *);
 void flush_tlb_page(struct vm_area_struct *, unsigned long);
 void flush_tlb_range(struct vm_area_struct *, unsigned long,
                unsigned long);
-
-static inline void flush_tlb_kernel_range(unsigned long start,
-               unsigned long end)
-{
-       flush_tlb_all();
-}
+void flush_tlb_kernel_range(unsigned long start, unsigned long end);
 
 #else /* !CONFIG_SMP */
 
@@ -58,7 +54,8 @@ static inline void flush_tlb_kernel_range(unsigned long start,
 #define flush_tlb_page(vma, page)         local_flush_tlb_page(vma, page)
 #define flush_tlb_range(vma, vmaddr, end)  local_flush_tlb_range(vma, vmaddr, \
                                                                 end)
-#define flush_tlb_kernel_range(start, end) local_flush_tlb_all()
+#define flush_tlb_kernel_range(start, end) local_flush_tlb_kernel_range(start, \
+                                                                       end)
 
 #endif /* CONFIG_SMP */
 
index 84fe931bb60e1f012417d202d002813b12cf68aa..9757bb74e53296f66372dd08506d94163e8801cc 100644 (file)
@@ -50,6 +50,7 @@
 #include <asm/param.h>
 #include <asm/traps.h>
 #include <asm/smp.h>
+#include <asm/sysmem.h>
 
 #include <platform/hardware.h>
 
@@ -88,12 +89,6 @@ static char __initdata command_line[COMMAND_LINE_SIZE];
 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 #endif
 
-sysmem_info_t __initdata sysmem;
-
-extern int mem_reserve(unsigned long, unsigned long, int);
-extern void bootmem_init(void);
-extern void zones_init(void);
-
 /*
  * Boot parameter parsing.
  *
@@ -113,31 +108,14 @@ typedef struct tagtable {
 
 /* parse current tag */
 
-static int __init add_sysmem_bank(unsigned long type, unsigned long start,
-               unsigned long end)
-{
-       if (sysmem.nr_banks >= SYSMEM_BANKS_MAX) {
-               printk(KERN_WARNING
-                               "Ignoring memory bank 0x%08lx size %ldKB\n",
-                               start, end - start);
-               return -EINVAL;
-       }
-       sysmem.bank[sysmem.nr_banks].type  = type;
-       sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(start);
-       sysmem.bank[sysmem.nr_banks].end   = end & PAGE_MASK;
-       sysmem.nr_banks++;
-
-       return 0;
-}
-
 static int __init parse_tag_mem(const bp_tag_t *tag)
 {
-       meminfo_t *mi = (meminfo_t *)(tag->data);
+       struct bp_meminfo *mi = (struct bp_meminfo *)(tag->data);
 
        if (mi->type != MEMORY_TYPE_CONVENTIONAL)
                return -1;
 
-       return add_sysmem_bank(mi->type, mi->start, mi->end);
+       return add_sysmem_bank(mi->start, mi->end);
 }
 
 __tagtable(BP_TAG_MEMORY, parse_tag_mem);
@@ -146,8 +124,8 @@ __tagtable(BP_TAG_MEMORY, parse_tag_mem);
 
 static int __init parse_tag_initrd(const bp_tag_t* tag)
 {
-       meminfo_t* mi;
-       mi = (meminfo_t*)(tag->data);
+       struct bp_meminfo *mi = (struct bp_meminfo *)(tag->data);
+
        initrd_start = (unsigned long)__va(mi->start);
        initrd_end = (unsigned long)__va(mi->end);
 
@@ -255,7 +233,7 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size)
                return;
 
        size &= PAGE_MASK;
-       add_sysmem_bank(MEMORY_TYPE_CONVENTIONAL, base, base + size);
+       add_sysmem_bank(base, base + size);
 }
 
 void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
@@ -292,8 +270,6 @@ device_initcall(xtensa_device_probe);
 
 void __init init_arch(bp_tag_t *bp_start)
 {
-       sysmem.nr_banks = 0;
-
        /* Parse boot parameters */
 
        if (bp_start)
@@ -304,10 +280,9 @@ void __init init_arch(bp_tag_t *bp_start)
 #endif
 
        if (sysmem.nr_banks == 0) {
-               sysmem.nr_banks = 1;
-               sysmem.bank[0].start = PLATFORM_DEFAULT_MEM_START;
-               sysmem.bank[0].end = PLATFORM_DEFAULT_MEM_START
-                                    + PLATFORM_DEFAULT_MEM_SIZE;
+               add_sysmem_bank(PLATFORM_DEFAULT_MEM_START,
+                               PLATFORM_DEFAULT_MEM_START +
+                               PLATFORM_DEFAULT_MEM_SIZE);
        }
 
 #ifdef CONFIG_CMDLINE_BOOL
@@ -487,7 +462,7 @@ void __init setup_arch(char **cmdline_p)
 #ifdef CONFIG_BLK_DEV_INITRD
        if (initrd_start < initrd_end) {
                initrd_is_mapped = mem_reserve(__pa(initrd_start),
-                                              __pa(initrd_end), 0);
+                                              __pa(initrd_end), 0) == 0;
                initrd_below_start_ok = 1;
        } else {
                initrd_start = 0;
@@ -532,6 +507,7 @@ void __init setup_arch(char **cmdline_p)
                    __pa(&_Level6InterruptVector_text_end), 0);
 #endif
 
+       parse_early_param();
        bootmem_init();
 
        unflatten_and_copy_device_tree();
index aa8bd8717927185bd5b422316885ddaa98d889f7..40b5a3771fb063fb02ffaa7fe07a426a3a684677 100644 (file)
@@ -496,6 +496,21 @@ void flush_tlb_range(struct vm_area_struct *vma,
        on_each_cpu(ipi_flush_tlb_range, &fd, 1);
 }
 
+static void ipi_flush_tlb_kernel_range(void *arg)
+{
+       struct flush_data *fd = arg;
+       local_flush_tlb_kernel_range(fd->addr1, fd->addr2);
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+       struct flush_data fd = {
+               .addr1 = start,
+               .addr2 = end,
+       };
+       on_each_cpu(ipi_flush_tlb_kernel_range, &fd, 1);
+}
+
 /* Cache flush functions */
 
 static void ipi_flush_cache_all(void *arg)
index 80b33ed51f31174fd41a53bebd957c140517d8f9..4d2872fd9bb5ebf89bb15127841e5ae28e8d9b58 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/in6.h>
 
 #include <asm/uaccess.h>
+#include <asm/cacheflush.h>
 #include <asm/checksum.h>
 #include <asm/dma.h>
 #include <asm/io.h>
@@ -105,6 +106,7 @@ EXPORT_SYMBOL(csum_partial_copy_generic);
  * Architecture-specific symbols
  */
 EXPORT_SYMBOL(__xtensa_copy_user);
+EXPORT_SYMBOL(__invalidate_icache_range);
 
 /*
  * Kernel hacking ...
@@ -127,3 +129,8 @@ EXPORT_SYMBOL(common_exception_return);
 #ifdef CONFIG_FUNCTION_TRACER
 EXPORT_SYMBOL(_mcount);
 #endif
+
+EXPORT_SYMBOL(__invalidate_dcache_range);
+#if XCHAL_DCACHE_IS_WRITEBACK
+EXPORT_SYMBOL(__flush_dcache_range);
+#endif
index f0b646d2f843feb5945601dbe65966a4a71cfec9..f54f78e24d7b5e72733f23da806272a4cba6b882 100644 (file)
@@ -4,3 +4,4 @@
 
 obj-y                  := init.o cache.o misc.o
 obj-$(CONFIG_MMU)      += fault.o mmu.o tlb.o
+obj-$(CONFIG_HIGHMEM)  += highmem.o
index ba4c47f291b17843047a410549b09cb59ba52967..63cbb867dadd64d8907176f1bd60420f8a41217a 100644 (file)
  *
  */
 
+#if (DCACHE_WAY_SIZE > PAGE_SIZE) && defined(CONFIG_HIGHMEM)
+#error "HIGHMEM is not supported on cores with aliasing cache."
+#endif
+
 #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
 
 /*
@@ -179,10 +183,11 @@ update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t *ptep)
 #else
        if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags)
            && (vma->vm_flags & VM_EXEC) != 0) {
-               unsigned long paddr = (unsigned long) page_address(page);
+               unsigned long paddr = (unsigned long)kmap_atomic(page);
                __flush_dcache_page(paddr);
                __invalidate_icache_page(paddr);
                set_bit(PG_arch_1, &page->flags);
+               kunmap_atomic((void *)paddr);
        }
 #endif
 }
diff --git a/arch/xtensa/mm/highmem.c b/arch/xtensa/mm/highmem.c
new file mode 100644 (file)
index 0000000..17a8c0d
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * High memory support for Xtensa architecture
+ *
+ * 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) 2014 Cadence Design Systems Inc.
+ */
+
+#include <linux/export.h>
+#include <linux/highmem.h>
+#include <asm/tlbflush.h>
+
+static pte_t *kmap_pte;
+
+void *kmap_atomic(struct page *page)
+{
+       enum fixed_addresses idx;
+       unsigned long vaddr;
+       int type;
+
+       pagefault_disable();
+       if (!PageHighMem(page))
+               return page_address(page);
+
+       type = kmap_atomic_idx_push();
+       idx = type + KM_TYPE_NR * smp_processor_id();
+       vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+#ifdef CONFIG_DEBUG_HIGHMEM
+       BUG_ON(!pte_none(*(kmap_pte - idx)));
+#endif
+       set_pte(kmap_pte - idx, mk_pte(page, PAGE_KERNEL_EXEC));
+
+       return (void *)vaddr;
+}
+EXPORT_SYMBOL(kmap_atomic);
+
+void __kunmap_atomic(void *kvaddr)
+{
+       int idx, type;
+
+       if (kvaddr >= (void *)FIXADDR_START &&
+           kvaddr < (void *)FIXADDR_TOP) {
+               type = kmap_atomic_idx();
+               idx = type + KM_TYPE_NR * smp_processor_id();
+
+               /*
+                * Force other mappings to Oops if they'll try to access this
+                * pte without first remap it.  Keeping stale mappings around
+                * is a bad idea also, in case the page changes cacheability
+                * attributes or becomes a protected page in a hypervisor.
+                */
+               pte_clear(&init_mm, kvaddr, kmap_pte - idx);
+               local_flush_tlb_kernel_range((unsigned long)kvaddr,
+                                            (unsigned long)kvaddr + PAGE_SIZE);
+
+               kmap_atomic_idx_pop();
+       }
+
+       pagefault_enable();
+}
+EXPORT_SYMBOL(__kunmap_atomic);
+
+void __init kmap_init(void)
+{
+       unsigned long kmap_vstart;
+
+       /* cache the first kmap pte */
+       kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
+       kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
+}
index aff108df92d3a301e8ba0ccaf7e13a5fb26c9038..4224256bb215f17c52d91662f186ecb250dee361 100644 (file)
@@ -8,6 +8,7 @@
  * for more details.
  *
  * Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
  *
  * Chris Zankel        <chris@zankel.net>
  * Joe Taylor  <joe@tensilica.com, joetylr@yahoo.com>
@@ -19,6 +20,7 @@
 #include <linux/errno.h>
 #include <linux/bootmem.h>
 #include <linux/gfp.h>
+#include <linux/highmem.h>
 #include <linux/swap.h>
 #include <linux/mman.h>
 #include <linux/nodemask.h>
 #include <asm/bootparam.h>
 #include <asm/page.h>
 #include <asm/sections.h>
+#include <asm/sysmem.h>
+
+struct sysmem_info sysmem __initdata;
+
+static void __init sysmem_dump(void)
+{
+       unsigned i;
+
+       pr_debug("Sysmem:\n");
+       for (i = 0; i < sysmem.nr_banks; ++i)
+               pr_debug("  0x%08lx - 0x%08lx (%ldK)\n",
+                        sysmem.bank[i].start, sysmem.bank[i].end,
+                        (sysmem.bank[i].end - sysmem.bank[i].start) >> 10);
+}
+
+/*
+ * Find bank with maximal .start such that bank.start <= start
+ */
+static inline struct meminfo * __init find_bank(unsigned long start)
+{
+       unsigned i;
+       struct meminfo *it = NULL;
+
+       for (i = 0; i < sysmem.nr_banks; ++i)
+               if (sysmem.bank[i].start <= start)
+                       it = sysmem.bank + i;
+               else
+                       break;
+       return it;
+}
+
+/*
+ * Move all memory banks starting at 'from' to a new place at 'to',
+ * adjust nr_banks accordingly.
+ * Both 'from' and 'to' must be inside the sysmem.bank.
+ *
+ * Returns: 0 (success), -ENOMEM (not enough space in the sysmem.bank).
+ */
+static int __init move_banks(struct meminfo *to, struct meminfo *from)
+{
+       unsigned n = sysmem.nr_banks - (from - sysmem.bank);
+
+       if (to > from && to - from + sysmem.nr_banks > SYSMEM_BANKS_MAX)
+               return -ENOMEM;
+       if (to != from)
+               memmove(to, from, n * sizeof(struct meminfo));
+       sysmem.nr_banks += to - from;
+       return 0;
+}
+
+/*
+ * Add new bank to sysmem. Resulting sysmem is the union of bytes of the
+ * original sysmem and the new bank.
+ *
+ * Returns: 0 (success), < 0 (error)
+ */
+int __init add_sysmem_bank(unsigned long start, unsigned long end)
+{
+       unsigned i;
+       struct meminfo *it = NULL;
+       unsigned long sz;
+       unsigned long bank_sz = 0;
+
+       if (start == end ||
+           (start < end) != (PAGE_ALIGN(start) < (end & PAGE_MASK))) {
+               pr_warn("Ignoring small memory bank 0x%08lx size: %ld bytes\n",
+                       start, end - start);
+               return -EINVAL;
+       }
+
+       start = PAGE_ALIGN(start);
+       end &= PAGE_MASK;
+       sz = end - start;
+
+       it = find_bank(start);
+
+       if (it)
+               bank_sz = it->end - it->start;
+
+       if (it && bank_sz >= start - it->start) {
+               if (end - it->start > bank_sz)
+                       it->end = end;
+               else
+                       return 0;
+       } else {
+               if (!it)
+                       it = sysmem.bank;
+               else
+                       ++it;
+
+               if (it - sysmem.bank < sysmem.nr_banks &&
+                   it->start - start <= sz) {
+                       it->start = start;
+                       if (it->end - it->start < sz)
+                               it->end = end;
+                       else
+                               return 0;
+               } else {
+                       if (move_banks(it + 1, it) < 0) {
+                               pr_warn("Ignoring memory bank 0x%08lx size %ld bytes\n",
+                                       start, end - start);
+                               return -EINVAL;
+                       }
+                       it->start = start;
+                       it->end = end;
+                       return 0;
+               }
+       }
+       sz = it->end - it->start;
+       for (i = it + 1 - sysmem.bank; i < sysmem.nr_banks; ++i)
+               if (sysmem.bank[i].start - it->start <= sz) {
+                       if (sz < sysmem.bank[i].end - it->start)
+                               it->end = sysmem.bank[i].end;
+               } else {
+                       break;
+               }
+
+       move_banks(it + 1, sysmem.bank + i);
+       return 0;
+}
 
 /*
  * mem_reserve(start, end, must_exist)
  *
  * Reserve some memory from the memory pool.
+ * If must_exist is set and a part of the region being reserved does not exist
+ * memory map is not altered.
  *
  * Parameters:
  *  start      Start of region,
  *  must_exist Must exist in memory pool.
  *
  * Returns:
- *  0 (memory area couldn't be mapped)
- * -1 (success)
+ *  0 (success)
+ *  < 0 (error)
  */
 
 int __init mem_reserve(unsigned long start, unsigned long end, int must_exist)
 {
-       int i;
-
-       if (start == end)
-               return 0;
+       struct meminfo *it;
+       struct meminfo *rm = NULL;
+       unsigned long sz;
+       unsigned long bank_sz = 0;
 
        start = start & PAGE_MASK;
        end = PAGE_ALIGN(end);
+       sz = end - start;
+       if (!sz)
+               return -EINVAL;
 
-       for (i = 0; i < sysmem.nr_banks; i++)
-               if (start < sysmem.bank[i].end
-                   && end >= sysmem.bank[i].start)
-                       break;
+       it = find_bank(start);
+
+       if (it)
+               bank_sz = it->end - it->start;
 
-       if (i == sysmem.nr_banks) {
-               if (must_exist)
-                       printk (KERN_WARNING "mem_reserve: [0x%0lx, 0x%0lx) "
-                               "not in any region!\n", start, end);
-               return 0;
+       if ((!it || end - it->start > bank_sz) && must_exist) {
+               pr_warn("mem_reserve: [0x%0lx, 0x%0lx) not in any region!\n",
+                       start, end);
+               return -EINVAL;
        }
 
-       if (start > sysmem.bank[i].start) {
-               if (end < sysmem.bank[i].end) {
-                       /* split entry */
-                       if (sysmem.nr_banks >= SYSMEM_BANKS_MAX)
-                               panic("meminfo overflow\n");
-                       sysmem.bank[sysmem.nr_banks].start = end;
-                       sysmem.bank[sysmem.nr_banks].end = sysmem.bank[i].end;
-                       sysmem.nr_banks++;
+       if (it && start - it->start < bank_sz) {
+               if (start == it->start) {
+                       if (end - it->start < bank_sz) {
+                               it->start = end;
+                               return 0;
+                       } else {
+                               rm = it;
+                       }
+               } else {
+                       it->end = start;
+                       if (end - it->start < bank_sz)
+                               return add_sysmem_bank(end,
+                                                      it->start + bank_sz);
+                       ++it;
                }
-               sysmem.bank[i].end = start;
+       }
 
-       } else if (end < sysmem.bank[i].end) {
-               sysmem.bank[i].start = end;
+       if (!it)
+               it = sysmem.bank;
 
-       } else {
-               /* remove entry */
-               sysmem.nr_banks--;
-               sysmem.bank[i].start = sysmem.bank[sysmem.nr_banks].start;
-               sysmem.bank[i].end   = sysmem.bank[sysmem.nr_banks].end;
+       for (; it < sysmem.bank + sysmem.nr_banks; ++it) {
+               if (it->end - start <= sz) {
+                       if (!rm)
+                               rm = it;
+               } else {
+                       if (it->start - start < sz)
+                               it->start = end;
+                       break;
+               }
        }
-       return -1;
+
+       if (rm)
+               move_banks(rm, it);
+
+       return 0;
 }
 
 
@@ -99,6 +239,7 @@ void __init bootmem_init(void)
        unsigned long bootmap_start, bootmap_size;
        int i;
 
+       sysmem_dump();
        max_low_pfn = max_pfn = 0;
        min_low_pfn = ~0;
 
@@ -156,19 +297,13 @@ void __init bootmem_init(void)
 
 void __init zones_init(void)
 {
-       unsigned long zones_size[MAX_NR_ZONES];
-       int i;
-
        /* All pages are DMA-able, so we put them all in the DMA zone. */
-
-       zones_size[ZONE_DMA] = max_low_pfn - ARCH_PFN_OFFSET;
-       for (i = 1; i < MAX_NR_ZONES; i++)
-               zones_size[i] = 0;
-
+       unsigned long zones_size[MAX_NR_ZONES] = {
+               [ZONE_DMA] = max_low_pfn - ARCH_PFN_OFFSET,
 #ifdef CONFIG_HIGHMEM
-       zones_size[ZONE_HIGHMEM] = max_pfn - max_low_pfn;
+               [ZONE_HIGHMEM] = max_pfn - max_low_pfn,
 #endif
-
+       };
        free_area_init_node(0, zones_size, ARCH_PFN_OFFSET, NULL);
 }
 
@@ -178,16 +313,38 @@ void __init zones_init(void)
 
 void __init mem_init(void)
 {
-       max_mapnr = max_low_pfn - ARCH_PFN_OFFSET;
-       high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
-
 #ifdef CONFIG_HIGHMEM
-#error HIGHGMEM not implemented in init.c
+       unsigned long tmp;
+
+       reset_all_zones_managed_pages();
+       for (tmp = max_low_pfn; tmp < max_pfn; tmp++)
+               free_highmem_page(pfn_to_page(tmp));
 #endif
 
+       max_mapnr = max_pfn - ARCH_PFN_OFFSET;
+       high_memory = (void *)__va(max_low_pfn << PAGE_SHIFT);
+
        free_all_bootmem();
 
        mem_init_print_info(NULL);
+       pr_info("virtual kernel memory layout:\n"
+#ifdef CONFIG_HIGHMEM
+               "    pkmap   : 0x%08lx - 0x%08lx  (%5lu kB)\n"
+               "    fixmap  : 0x%08lx - 0x%08lx  (%5lu kB)\n"
+#endif
+               "    vmalloc : 0x%08x - 0x%08x  (%5u MB)\n"
+               "    lowmem  : 0x%08x - 0x%08lx  (%5lu MB)\n",
+#ifdef CONFIG_HIGHMEM
+               PKMAP_BASE, PKMAP_BASE + LAST_PKMAP * PAGE_SIZE,
+               (LAST_PKMAP*PAGE_SIZE) >> 10,
+               FIXADDR_START, FIXADDR_TOP,
+               (FIXADDR_TOP - FIXADDR_START) >> 10,
+#endif
+               VMALLOC_START, VMALLOC_END,
+               (VMALLOC_END - VMALLOC_START) >> 20,
+               PAGE_OFFSET, PAGE_OFFSET +
+               (max_low_pfn - min_low_pfn) * PAGE_SIZE,
+               ((max_low_pfn - min_low_pfn) * PAGE_SIZE) >> 20);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -204,3 +361,53 @@ void free_initmem(void)
 {
        free_initmem_default(-1);
 }
+
+static void __init parse_memmap_one(char *p)
+{
+       char *oldp;
+       unsigned long start_at, mem_size;
+
+       if (!p)
+               return;
+
+       oldp = p;
+       mem_size = memparse(p, &p);
+       if (p == oldp)
+               return;
+
+       switch (*p) {
+       case '@':
+               start_at = memparse(p + 1, &p);
+               add_sysmem_bank(start_at, start_at + mem_size);
+               break;
+
+       case '$':
+               start_at = memparse(p + 1, &p);
+               mem_reserve(start_at, start_at + mem_size, 0);
+               break;
+
+       case 0:
+               mem_reserve(mem_size, 0, 0);
+               break;
+
+       default:
+               pr_warn("Unrecognized memmap syntax: %s\n", p);
+               break;
+       }
+}
+
+static int __init parse_memmap_opt(char *str)
+{
+       while (str) {
+               char *k = strchr(str, ',');
+
+               if (k)
+                       *k++ = 0;
+
+               parse_memmap_one(str);
+               str = k;
+       }
+
+       return 0;
+}
+early_param("memmap", parse_memmap_opt);
index 861203e958da828deb140122752e95b47ddbf35f..3429b483d9f85cd2495e01c8c0a11d05bc22e16c 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Extracted from init.c
  */
+#include <linux/bootmem.h>
 #include <linux/percpu.h>
 #include <linux/init.h>
 #include <linux/string.h>
 #include <asm/initialize_mmu.h>
 #include <asm/io.h>
 
+#if defined(CONFIG_HIGHMEM)
+static void * __init init_pmd(unsigned long vaddr)
+{
+       pgd_t *pgd = pgd_offset_k(vaddr);
+       pmd_t *pmd = pmd_offset(pgd, vaddr);
+
+       if (pmd_none(*pmd)) {
+               unsigned i;
+               pte_t *pte = alloc_bootmem_low_pages(PAGE_SIZE);
+
+               for (i = 0; i < 1024; i++)
+                       pte_clear(NULL, 0, pte + i);
+
+               set_pmd(pmd, __pmd(((unsigned long)pte) & PAGE_MASK));
+               BUG_ON(pte != pte_offset_kernel(pmd, 0));
+               pr_debug("%s: vaddr: 0x%08lx, pmd: 0x%p, pte: 0x%p\n",
+                        __func__, vaddr, pmd, pte);
+               return pte;
+       } else {
+               return pte_offset_kernel(pmd, 0);
+       }
+}
+
+static void __init fixedrange_init(void)
+{
+       BUILD_BUG_ON(FIXADDR_SIZE > PMD_SIZE);
+       init_pmd(__fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK);
+}
+#endif
+
 void __init paging_init(void)
 {
        memset(swapper_pg_dir, 0, PAGE_SIZE);
+#ifdef CONFIG_HIGHMEM
+       fixedrange_init();
+       pkmap_page_table = init_pmd(PKMAP_BASE);
+       kmap_init();
+#endif
 }
 
 /*
index ade623826788b387f150cfae5a90821f07f6b028..5ece856c5725c7cc72d0a0175bf9229330fabec5 100644 (file)
@@ -149,6 +149,21 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
        local_irq_restore(flags);
 }
 
+void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+       if (end > start && start >= TASK_SIZE && end <= PAGE_OFFSET &&
+           end - start < _TLB_ENTRIES << PAGE_SHIFT) {
+               start &= PAGE_MASK;
+               while (start < end) {
+                       invalidate_itlb_mapping(start);
+                       invalidate_dtlb_mapping(start);
+                       start += PAGE_SIZE;
+               }
+       } else {
+               local_flush_tlb_all();
+       }
+}
+
 #ifdef CONFIG_DEBUG_TLB_SANITY
 
 static unsigned get_pte_for_vaddr(unsigned vaddr)
index d2369b799c5077f7b9240135cba96d74acfcc7cf..b3e89291cfbafcb35a1eb07f7f584c35ef7f2d81 100644 (file)
@@ -4,6 +4,7 @@
 # "prom monitor" library routines under Linux.
 #
 
-obj-y                  = console.o setup.o
+obj-y                  = setup.o
+obj-$(CONFIG_TTY)      += console.o
 obj-$(CONFIG_NET)      += network.o
 obj-$(CONFIG_BLK_DEV_SIMDISK) += simdisk.o
index f9bc8796629089a540c892109a46a9fe19f68568..b90555cb80890135fee12f7cc3ec361127106836 100644 (file)
@@ -92,18 +92,8 @@ void __init platform_setup(char** cmdline)
 
 /* early initialization */
 
-extern sysmem_info_t __initdata sysmem;
-
-void platform_init(bp_tag_t* first)
+void __init platform_init(bp_tag_t *first)
 {
-       /* Set default memory block if not provided by the bootloader. */
-
-       if (sysmem.nr_banks == 0) {
-               sysmem.nr_banks = 1;
-               sysmem.bank[0].start = PLATFORM_DEFAULT_MEM_START;
-               sysmem.bank[0].end = PLATFORM_DEFAULT_MEM_START
-                                    + PLATFORM_DEFAULT_MEM_SIZE;
-       }
 }
 
 /* Heartbeat. Let the LED blink. */
index e4a4145926f629787ce0647f3036a98298c8f055..1039fb9ff5f5f998628884dedab422c9b405a36c 100644 (file)
@@ -451,7 +451,20 @@ static int blkcg_reset_stats(struct cgroup_subsys_state *css,
        struct blkcg_gq *blkg;
        int i;
 
-       mutex_lock(&blkcg_pol_mutex);
+       /*
+        * XXX: We invoke cgroup_add/rm_cftypes() under blkcg_pol_mutex
+        * which ends up putting cgroup's internal cgroup_tree_mutex under
+        * it; however, cgroup_tree_mutex is nested above cgroup file
+        * active protection and grabbing blkcg_pol_mutex from a cgroup
+        * file operation creates a possible circular dependency.  cgroup
+        * internal locking is planned to go through further simplification
+        * and this issue should go away soon.  For now, let's trylock
+        * blkcg_pol_mutex and restart the write on failure.
+        *
+        * http://lkml.kernel.org/g/5363C04B.4010400@oracle.com
+        */
+       if (!mutex_trylock(&blkcg_pol_mutex))
+               return restart_syscall();
        spin_lock_irq(&blkcg->lock);
 
        /*
index 1512e41cd93d74a4e7ab3fde6809e64468f797a8..43665d0d0905ddddf018fe68655c1ff7685b0b9e 100644 (file)
@@ -466,7 +466,7 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        type -= CRYPTO_MSG_BASE;
        link = &crypto_dispatch[type];
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
        if ((type == (CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE) &&
index d05d81b19b50c229b2aa100bf01f8ac2818c0c1c..7183b6af5dac2b72fc53edc7044d743eac57ed45 100644 (file)
@@ -119,7 +119,7 @@ obj-$(CONFIG_SGI_SN)                += sn/
 obj-y                          += firmware/
 obj-$(CONFIG_CRYPTO)           += crypto/
 obj-$(CONFIG_SUPERH)           += sh/
-obj-$(CONFIG_ARCH_SHMOBILE_LEGACY)     += sh/
+obj-$(CONFIG_ARCH_SHMOBILE)    += sh/
 ifndef CONFIG_ARCH_USES_GETTIMEOFFSET
 obj-y                          += clocksource/
 endif
index ab686b31010034083ba3b4784ba288fb93b3f554..a34a22841002495713a74f960dea482ecee8dc11 100644 (file)
@@ -47,6 +47,23 @@ config ACPI_SLEEP
        depends on SUSPEND || HIBERNATION
        default y
 
+config ACPI_PROCFS_POWER
+       bool "Deprecated power /proc/acpi directories"
+       depends on PROC_FS
+       help
+         For backwards compatibility, this option allows
+          deprecated power /proc/acpi/ directories to exist, even when
+          they have been replaced by functions in /sys.
+          The deprecated directories (and their replacements) include:
+         /proc/acpi/battery/* (/sys/class/power_supply/*)
+         /proc/acpi/ac_adapter/* (sys/class/power_supply/*)
+         This option has no effect on /proc/acpi/ directories
+         and functions, which do not yet exist in /sys
+         This option, together with the proc directories, will be
+         deleted in the future.
+
+         Say N to delete power /proc/acpi/ directories that have moved to /sys/
+
 config ACPI_EC_DEBUGFS
        tristate "EC read/write access through /sys/kernel/debug/ec"
        default n
index 0331f91d56e663d63a7268d1a77bb3ae1080f715..bce34afadcd05d250831f098ca533565750345e6 100644 (file)
@@ -47,6 +47,7 @@ acpi-y                                += sysfs.o
 acpi-$(CONFIG_X86)             += acpi_cmos_rtc.o
 acpi-$(CONFIG_DEBUG_FS)                += debugfs.o
 acpi-$(CONFIG_ACPI_NUMA)       += numa.o
+acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
 ifdef CONFIG_ACPI_VIDEO
 acpi-y                         += video_detect.o
 endif
index 2c01c1da29ce39f637136a12a512f2a473333233..c67f6f5ad61107b7ded8069a53894763e91ab892 100644 (file)
@@ -52,11 +52,39 @@ MODULE_AUTHOR("Paul Diefenbaugh");
 MODULE_DESCRIPTION("ACPI AC Adapter Driver");
 MODULE_LICENSE("GPL");
 
+static int acpi_ac_add(struct acpi_device *device);
+static int acpi_ac_remove(struct acpi_device *device);
+static void acpi_ac_notify(struct acpi_device *device, u32 event);
+
+static const struct acpi_device_id ac_device_ids[] = {
+       {"ACPI0003", 0},
+       {"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, ac_device_ids);
+
+#ifdef CONFIG_PM_SLEEP
+static int acpi_ac_resume(struct device *dev);
+#endif
+static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume);
+
 static int ac_sleep_before_get_state_ms;
 
+static struct acpi_driver acpi_ac_driver = {
+       .name = "ac",
+       .class = ACPI_AC_CLASS,
+       .ids = ac_device_ids,
+       .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
+       .ops = {
+               .add = acpi_ac_add,
+               .remove = acpi_ac_remove,
+               .notify = acpi_ac_notify,
+               },
+       .drv.pm = &acpi_ac_pm,
+};
+
 struct acpi_ac {
        struct power_supply charger;
-       struct platform_device *pdev;
+       struct acpi_device * device;
        unsigned long long state;
        struct notifier_block battery_nb;
 };
@@ -69,10 +97,12 @@ struct acpi_ac {
 
 static int acpi_ac_get_state(struct acpi_ac *ac)
 {
-       acpi_status status;
-       acpi_handle handle = ACPI_HANDLE(&ac->pdev->dev);
+       acpi_status status = AE_OK;
+
+       if (!ac)
+               return -EINVAL;
 
-       status = acpi_evaluate_integer(handle, "_PSR", NULL,
+       status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL,
                                       &ac->state);
        if (ACPI_FAILURE(status)) {
                ACPI_EXCEPTION((AE_INFO, status,
@@ -117,10 +147,9 @@ static enum power_supply_property ac_props[] = {
                                    Driver Model
    -------------------------------------------------------------------------- */
 
-static void acpi_ac_notify_handler(acpi_handle handle, u32 event, void *data)
+static void acpi_ac_notify(struct acpi_device *device, u32 event)
 {
-       struct acpi_ac *ac = data;
-       struct acpi_device *adev;
+       struct acpi_ac *ac = acpi_driver_data(device);
 
        if (!ac)
                return;
@@ -143,11 +172,10 @@ static void acpi_ac_notify_handler(acpi_handle handle, u32 event, void *data)
                        msleep(ac_sleep_before_get_state_ms);
 
                acpi_ac_get_state(ac);
-               adev = ACPI_COMPANION(&ac->pdev->dev);
-               acpi_bus_generate_netlink_event(adev->pnp.device_class,
-                                               dev_name(&ac->pdev->dev),
-                                               event, (u32) ac->state);
-               acpi_notifier_call_chain(adev, event, (u32) ac->state);
+               acpi_bus_generate_netlink_event(device->pnp.device_class,
+                                                 dev_name(&device->dev), event,
+                                                 (u32) ac->state);
+               acpi_notifier_call_chain(device, event, (u32) ac->state);
                kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
        }
 
@@ -192,49 +220,39 @@ static struct dmi_system_id ac_dmi_table[] = {
        {},
 };
 
-static int acpi_ac_probe(struct platform_device *pdev)
+static int acpi_ac_add(struct acpi_device *device)
 {
        int result = 0;
        struct acpi_ac *ac = NULL;
-       struct acpi_device *adev;
 
-       if (!pdev)
-               return -EINVAL;
 
-       adev = ACPI_COMPANION(&pdev->dev);
-       if (!adev)
-               return -ENODEV;
+       if (!device)
+               return -EINVAL;
 
        ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL);
        if (!ac)
                return -ENOMEM;
 
-       strcpy(acpi_device_name(adev), ACPI_AC_DEVICE_NAME);
-       strcpy(acpi_device_class(adev), ACPI_AC_CLASS);
-       ac->pdev = pdev;
-       platform_set_drvdata(pdev, ac);
+       ac->device = device;
+       strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME);
+       strcpy(acpi_device_class(device), ACPI_AC_CLASS);
+       device->driver_data = ac;
 
        result = acpi_ac_get_state(ac);
        if (result)
                goto end;
 
-       ac->charger.name = acpi_device_bid(adev);
+       ac->charger.name = acpi_device_bid(device);
        ac->charger.type = POWER_SUPPLY_TYPE_MAINS;
        ac->charger.properties = ac_props;
        ac->charger.num_properties = ARRAY_SIZE(ac_props);
        ac->charger.get_property = get_ac_property;
-       result = power_supply_register(&pdev->dev, &ac->charger);
+       result = power_supply_register(&ac->device->dev, &ac->charger);
        if (result)
                goto end;
 
-       result = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev),
-                       ACPI_ALL_NOTIFY, acpi_ac_notify_handler, ac);
-       if (result) {
-               power_supply_unregister(&ac->charger);
-               goto end;
-       }
        printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
-              acpi_device_name(adev), acpi_device_bid(adev),
+              acpi_device_name(device), acpi_device_bid(device),
               ac->state ? "on-line" : "off-line");
 
        ac->battery_nb.notifier_call = acpi_ac_battery_notify;
@@ -256,7 +274,7 @@ static int acpi_ac_resume(struct device *dev)
        if (!dev)
                return -EINVAL;
 
-       ac = platform_get_drvdata(to_platform_device(dev));
+       ac = acpi_driver_data(to_acpi_device(dev));
        if (!ac)
                return -EINVAL;
 
@@ -270,19 +288,17 @@ static int acpi_ac_resume(struct device *dev)
 #else
 #define acpi_ac_resume NULL
 #endif
-static SIMPLE_DEV_PM_OPS(acpi_ac_pm_ops, NULL, acpi_ac_resume);
 
-static int acpi_ac_remove(struct platform_device *pdev)
+static int acpi_ac_remove(struct acpi_device *device)
 {
-       struct acpi_ac *ac;
+       struct acpi_ac *ac = NULL;
+
 
-       if (!pdev)
+       if (!device || !acpi_driver_data(device))
                return -EINVAL;
 
-       acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev),
-                       ACPI_ALL_NOTIFY, acpi_ac_notify_handler);
+       ac = acpi_driver_data(device);
 
-       ac = platform_get_drvdata(pdev);
        if (ac->charger.dev)
                power_supply_unregister(&ac->charger);
        unregister_acpi_notifier(&ac->battery_nb);
@@ -292,23 +308,6 @@ static int acpi_ac_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct acpi_device_id acpi_ac_match[] = {
-       { "ACPI0003", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(acpi, acpi_ac_match);
-
-static struct platform_driver acpi_ac_driver = {
-       .probe          = acpi_ac_probe,
-       .remove         = acpi_ac_remove,
-       .driver         = {
-               .name   = "acpi-ac",
-               .owner  = THIS_MODULE,
-               .pm     = &acpi_ac_pm_ops,
-               .acpi_match_table = ACPI_PTR(acpi_ac_match),
-       },
-};
-
 static int __init acpi_ac_init(void)
 {
        int result;
@@ -316,7 +315,7 @@ static int __init acpi_ac_init(void)
        if (acpi_disabled)
                return -ENODEV;
 
-       result = platform_driver_register(&acpi_ac_driver);
+       result = acpi_bus_register_driver(&acpi_ac_driver);
        if (result < 0)
                return -ENODEV;
 
@@ -325,7 +324,7 @@ static int __init acpi_ac_init(void)
 
 static void __exit acpi_ac_exit(void)
 {
-       platform_driver_unregister(&acpi_ac_driver);
+       acpi_bus_unregister_driver(&acpi_ac_driver);
 }
 module_init(acpi_ac_init);
 module_exit(acpi_ac_exit);
index dbfe49e5fd63cc179559b2c5caee57d27324c012..1d4950388fa13b9fc6050fbaf419ae68c796f24d 100644 (file)
@@ -29,7 +29,6 @@ ACPI_MODULE_NAME("platform");
 static const struct acpi_device_id acpi_platform_device_ids[] = {
 
        { "PNP0D40" },
-       { "ACPI0003" },
        { "VPC2004" },
        { "BCM4752" },
 
index b06f5f55ada952ced85de9c845dfb49cac421633..52c81c49cc7d8396fa5b36a4d24b757f934ced46 100644 (file)
@@ -405,7 +405,6 @@ static int acpi_processor_add(struct acpi_device *device,
                goto err;
 
        pr->dev = dev;
-       dev->offline = pr->flags.need_hotplug_init;
 
        /* Trigger the processor driver's .probe() if present. */
        if (device_attach(dev) >= 0)
index 49bbc71fad54efd709ba9b7e6a610b5f8a30a7a3..a08a448068dd99981be3eeb9643e0255b20ae8df 100644 (file)
@@ -141,9 +141,9 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_do_not_use_xsdt, FALSE);
  * address. Although ACPICA adheres to the ACPI specification which
  * requires the use of the corresponding 64-bit address if it is non-zero,
  * some machines have been found to have a corrupted non-zero 64-bit
- * address. Default is FALSE, do not favor the 32-bit addresses.
+ * address. Default is TRUE, favor the 32-bit addresses.
  */
-ACPI_INIT_GLOBAL(u8, acpi_gbl_use32_bit_fadt_addresses, FALSE);
+ACPI_INIT_GLOBAL(u8, acpi_gbl_use32_bit_fadt_addresses, TRUE);
 
 /*
  * Optionally truncate I/O addresses to 16 bits. Provides compatibility
index a4702eee91a820d131960754c14da6aa62f50939..9fb85f38de90e3b073635ef2b854895b13e7b5b8 100644 (file)
@@ -461,6 +461,7 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
        u32 table_count;
        struct acpi_table_header *table;
        acpi_physical_address address;
+       acpi_physical_address rsdt_address;
        u32 length;
        u8 *table_entry;
        acpi_status status;
@@ -488,11 +489,14 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
                 * as per the ACPI specification.
                 */
                address = (acpi_physical_address) rsdp->xsdt_physical_address;
+               rsdt_address =
+                   (acpi_physical_address) rsdp->rsdt_physical_address;
                table_entry_size = ACPI_XSDT_ENTRY_SIZE;
        } else {
                /* Root table is an RSDT (32-bit physical addresses) */
 
                address = (acpi_physical_address) rsdp->rsdt_physical_address;
+               rsdt_address = address;
                table_entry_size = ACPI_RSDT_ENTRY_SIZE;
        }
 
@@ -515,8 +519,7 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
 
                        /* Fall back to the RSDT */
 
-                       address =
-                           (acpi_physical_address) rsdp->rsdt_physical_address;
+                       address = rsdt_address;
                        table_entry_size = ACPI_RSDT_ENTRY_SIZE;
                }
        }
index 9a2c63b2005038476e5a5e77360fd836aad3f25f..6e7b2a12860d31ac533c730e97d080daaa6f1385 100644 (file)
 #include <linux/suspend.h>
 #include <asm/unaligned.h>
 
+#ifdef CONFIG_ACPI_PROCFS_POWER
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <asm/uaccess.h>
+#endif
+
 #include <linux/acpi.h>
 #include <linux/power_supply.h>
 
@@ -64,6 +70,19 @@ static unsigned int cache_time = 1000;
 module_param(cache_time, uint, 0644);
 MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
 
+#ifdef CONFIG_ACPI_PROCFS_POWER
+extern struct proc_dir_entry *acpi_lock_battery_dir(void);
+extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
+
+enum acpi_battery_files {
+       info_tag = 0,
+       state_tag,
+       alarm_tag,
+       ACPI_BATTERY_NUMFILES,
+};
+
+#endif
+
 static const struct acpi_device_id battery_device_ids[] = {
        {"PNP0C0A", 0},
        {"", 0},
@@ -299,6 +318,14 @@ static enum power_supply_property energy_battery_props[] = {
        POWER_SUPPLY_PROP_SERIAL_NUMBER,
 };
 
+#ifdef CONFIG_ACPI_PROCFS_POWER
+inline char *acpi_battery_units(struct acpi_battery *battery)
+{
+       return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ?
+               "mA" : "mW";
+}
+#endif
+
 /* --------------------------------------------------------------------------
                                Battery Management
    -------------------------------------------------------------------------- */
@@ -716,6 +743,279 @@ static void acpi_battery_refresh(struct acpi_battery *battery)
        sysfs_add_battery(battery);
 }
 
+/* --------------------------------------------------------------------------
+                              FS Interface (/proc)
+   -------------------------------------------------------------------------- */
+
+#ifdef CONFIG_ACPI_PROCFS_POWER
+static struct proc_dir_entry *acpi_battery_dir;
+
+static int acpi_battery_print_info(struct seq_file *seq, int result)
+{
+       struct acpi_battery *battery = seq->private;
+
+       if (result)
+               goto end;
+
+       seq_printf(seq, "present:                 %s\n",
+                  acpi_battery_present(battery) ? "yes" : "no");
+       if (!acpi_battery_present(battery))
+               goto end;
+       if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
+               seq_printf(seq, "design capacity:         unknown\n");
+       else
+               seq_printf(seq, "design capacity:         %d %sh\n",
+                          battery->design_capacity,
+                          acpi_battery_units(battery));
+
+       if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
+               seq_printf(seq, "last full capacity:      unknown\n");
+       else
+               seq_printf(seq, "last full capacity:      %d %sh\n",
+                          battery->full_charge_capacity,
+                          acpi_battery_units(battery));
+
+       seq_printf(seq, "battery technology:      %srechargeable\n",
+                  (!battery->technology)?"non-":"");
+
+       if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
+               seq_printf(seq, "design voltage:          unknown\n");
+       else
+               seq_printf(seq, "design voltage:          %d mV\n",
+                          battery->design_voltage);
+       seq_printf(seq, "design capacity warning: %d %sh\n",
+                  battery->design_capacity_warning,
+                  acpi_battery_units(battery));
+       seq_printf(seq, "design capacity low:     %d %sh\n",
+                  battery->design_capacity_low,
+                  acpi_battery_units(battery));
+       seq_printf(seq, "cycle count:             %i\n", battery->cycle_count);
+       seq_printf(seq, "capacity granularity 1:  %d %sh\n",
+                  battery->capacity_granularity_1,
+                  acpi_battery_units(battery));
+       seq_printf(seq, "capacity granularity 2:  %d %sh\n",
+                  battery->capacity_granularity_2,
+                  acpi_battery_units(battery));
+       seq_printf(seq, "model number:            %s\n", battery->model_number);
+       seq_printf(seq, "serial number:           %s\n", battery->serial_number);
+       seq_printf(seq, "battery type:            %s\n", battery->type);
+       seq_printf(seq, "OEM info:                %s\n", battery->oem_info);
+      end:
+       if (result)
+               seq_printf(seq, "ERROR: Unable to read battery info\n");
+       return result;
+}
+
+static int acpi_battery_print_state(struct seq_file *seq, int result)
+{
+       struct acpi_battery *battery = seq->private;
+
+       if (result)
+               goto end;
+
+       seq_printf(seq, "present:                 %s\n",
+                  acpi_battery_present(battery) ? "yes" : "no");
+       if (!acpi_battery_present(battery))
+               goto end;
+
+       seq_printf(seq, "capacity state:          %s\n",
+                       (battery->state & 0x04) ? "critical" : "ok");
+       if ((battery->state & 0x01) && (battery->state & 0x02))
+               seq_printf(seq,
+                          "charging state:          charging/discharging\n");
+       else if (battery->state & 0x01)
+               seq_printf(seq, "charging state:          discharging\n");
+       else if (battery->state & 0x02)
+               seq_printf(seq, "charging state:          charging\n");
+       else
+               seq_printf(seq, "charging state:          charged\n");
+
+       if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
+               seq_printf(seq, "present rate:            unknown\n");
+       else
+               seq_printf(seq, "present rate:            %d %s\n",
+                          battery->rate_now, acpi_battery_units(battery));
+
+       if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
+               seq_printf(seq, "remaining capacity:      unknown\n");
+       else
+               seq_printf(seq, "remaining capacity:      %d %sh\n",
+                          battery->capacity_now, acpi_battery_units(battery));
+       if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
+               seq_printf(seq, "present voltage:         unknown\n");
+       else
+               seq_printf(seq, "present voltage:         %d mV\n",
+                          battery->voltage_now);
+      end:
+       if (result)
+               seq_printf(seq, "ERROR: Unable to read battery state\n");
+
+       return result;
+}
+
+static int acpi_battery_print_alarm(struct seq_file *seq, int result)
+{
+       struct acpi_battery *battery = seq->private;
+
+       if (result)
+               goto end;
+
+       if (!acpi_battery_present(battery)) {
+               seq_printf(seq, "present:                 no\n");
+               goto end;
+       }
+       seq_printf(seq, "alarm:                   ");
+       if (!battery->alarm)
+               seq_printf(seq, "unsupported\n");
+       else
+               seq_printf(seq, "%u %sh\n", battery->alarm,
+                               acpi_battery_units(battery));
+      end:
+       if (result)
+               seq_printf(seq, "ERROR: Unable to read battery alarm\n");
+       return result;
+}
+
+static ssize_t acpi_battery_write_alarm(struct file *file,
+                                       const char __user * buffer,
+                                       size_t count, loff_t * ppos)
+{
+       int result = 0;
+       char alarm_string[12] = { '\0' };
+       struct seq_file *m = file->private_data;
+       struct acpi_battery *battery = m->private;
+
+       if (!battery || (count > sizeof(alarm_string) - 1))
+               return -EINVAL;
+       if (!acpi_battery_present(battery)) {
+               result = -ENODEV;
+               goto end;
+       }
+       if (copy_from_user(alarm_string, buffer, count)) {
+               result = -EFAULT;
+               goto end;
+       }
+       alarm_string[count] = '\0';
+       battery->alarm = simple_strtol(alarm_string, NULL, 0);
+       result = acpi_battery_set_alarm(battery);
+      end:
+       if (!result)
+               return count;
+       return result;
+}
+
+typedef int(*print_func)(struct seq_file *seq, int result);
+
+static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = {
+       acpi_battery_print_info,
+       acpi_battery_print_state,
+       acpi_battery_print_alarm,
+};
+
+static int acpi_battery_read(int fid, struct seq_file *seq)
+{
+       struct acpi_battery *battery = seq->private;
+       int result = acpi_battery_update(battery);
+       return acpi_print_funcs[fid](seq, result);
+}
+
+#define DECLARE_FILE_FUNCTIONS(_name) \
+static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \
+{ \
+       return acpi_battery_read(_name##_tag, seq); \
+} \
+static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \
+{ \
+       return single_open(file, acpi_battery_read_##_name, PDE_DATA(inode)); \
+}
+
+DECLARE_FILE_FUNCTIONS(info);
+DECLARE_FILE_FUNCTIONS(state);
+DECLARE_FILE_FUNCTIONS(alarm);
+
+#undef DECLARE_FILE_FUNCTIONS
+
+#define FILE_DESCRIPTION_RO(_name) \
+       { \
+       .name = __stringify(_name), \
+       .mode = S_IRUGO, \
+       .ops = { \
+               .open = acpi_battery_##_name##_open_fs, \
+               .read = seq_read, \
+               .llseek = seq_lseek, \
+               .release = single_release, \
+               .owner = THIS_MODULE, \
+               }, \
+       }
+
+#define FILE_DESCRIPTION_RW(_name) \
+       { \
+       .name = __stringify(_name), \
+       .mode = S_IFREG | S_IRUGO | S_IWUSR, \
+       .ops = { \
+               .open = acpi_battery_##_name##_open_fs, \
+               .read = seq_read, \
+               .llseek = seq_lseek, \
+               .write = acpi_battery_write_##_name, \
+               .release = single_release, \
+               .owner = THIS_MODULE, \
+               }, \
+       }
+
+static const struct battery_file {
+       struct file_operations ops;
+       umode_t mode;
+       const char *name;
+} acpi_battery_file[] = {
+       FILE_DESCRIPTION_RO(info),
+       FILE_DESCRIPTION_RO(state),
+       FILE_DESCRIPTION_RW(alarm),
+};
+
+#undef FILE_DESCRIPTION_RO
+#undef FILE_DESCRIPTION_RW
+
+static int acpi_battery_add_fs(struct acpi_device *device)
+{
+       struct proc_dir_entry *entry = NULL;
+       int i;
+
+       printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded,"
+                       " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
+       if (!acpi_device_dir(device)) {
+               acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
+                                                    acpi_battery_dir);
+               if (!acpi_device_dir(device))
+                       return -ENODEV;
+       }
+
+       for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
+               entry = proc_create_data(acpi_battery_file[i].name,
+                                        acpi_battery_file[i].mode,
+                                        acpi_device_dir(device),
+                                        &acpi_battery_file[i].ops,
+                                        acpi_driver_data(device));
+               if (!entry)
+                       return -ENODEV;
+       }
+       return 0;
+}
+
+static void acpi_battery_remove_fs(struct acpi_device *device)
+{
+       int i;
+       if (!acpi_device_dir(device))
+               return;
+       for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i)
+               remove_proc_entry(acpi_battery_file[i].name,
+                                 acpi_device_dir(device));
+
+       remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
+       acpi_device_dir(device) = NULL;
+}
+
+#endif
+
 /* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
@@ -790,6 +1090,15 @@ static int acpi_battery_add(struct acpi_device *device)
        result = acpi_battery_update(battery);
        if (result)
                goto fail;
+#ifdef CONFIG_ACPI_PROCFS_POWER
+       result = acpi_battery_add_fs(device);
+#endif
+       if (result) {
+#ifdef CONFIG_ACPI_PROCFS_POWER
+               acpi_battery_remove_fs(device);
+#endif
+               goto fail;
+       }
 
        printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
                ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
@@ -816,6 +1125,9 @@ static int acpi_battery_remove(struct acpi_device *device)
                return -EINVAL;
        battery = acpi_driver_data(device);
        unregister_pm_notifier(&battery->pm_nb);
+#ifdef CONFIG_ACPI_PROCFS_POWER
+       acpi_battery_remove_fs(device);
+#endif
        sysfs_remove_battery(battery);
        mutex_destroy(&battery->lock);
        mutex_destroy(&battery->sysfs_lock);
@@ -866,7 +1178,19 @@ static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
 
        if (dmi_check_system(bat_dmi_table))
                battery_bix_broken_package = 1;
-       acpi_bus_register_driver(&acpi_battery_driver);
+       
+#ifdef CONFIG_ACPI_PROCFS_POWER
+       acpi_battery_dir = acpi_lock_battery_dir();
+       if (!acpi_battery_dir)
+               return;
+#endif
+       if (acpi_bus_register_driver(&acpi_battery_driver) < 0) {
+#ifdef CONFIG_ACPI_PROCFS_POWER
+               acpi_unlock_battery_dir(acpi_battery_dir);
+#endif
+               return;
+       }
+       return;
 }
 
 static int __init acpi_battery_init(void)
@@ -878,6 +1202,9 @@ static int __init acpi_battery_init(void)
 static void __exit acpi_battery_exit(void)
 {
        acpi_bus_unregister_driver(&acpi_battery_driver);
+#ifdef CONFIG_ACPI_PROCFS_POWER
+       acpi_unlock_battery_dir(acpi_battery_dir);
+#endif
 }
 
 module_init(acpi_battery_init);
index afec4526c48aa04e2921a199396e8fb2ea7489be..3d8413d02a975f0643275a247524a0c9d7569341 100644 (file)
@@ -314,6 +314,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
                     DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"),
                },
        },
+       {
+       .callback = dmi_disable_osi_win8,
+       .ident = "Dell Inspiron 7737",
+       .matches = {
+                   DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                   DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7737"),
+               },
+       },
 
        /*
         * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
@@ -374,6 +382,19 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
                     DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T500"),
                },
        },
+       /*
+        * Without this this EEEpc exports a non working WMI interface, with
+        * this it exports a working "good old" eeepc_laptop interface, fixing
+        * both brightness control, and rfkill not working.
+        */
+       {
+       .callback = dmi_enable_osi_linux,
+       .ident = "Asus EEE PC 1015PX",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
+                    DMI_MATCH(DMI_PRODUCT_NAME, "1015PX"),
+               },
+       },
        {}
 };
 
diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c
new file mode 100644 (file)
index 0000000..6c9ee68
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/acpi.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+#define PREFIX "ACPI: "
+
+ACPI_MODULE_NAME("cm_sbs");
+#define ACPI_AC_CLASS          "ac_adapter"
+#define ACPI_BATTERY_CLASS     "battery"
+#define _COMPONENT             ACPI_SBS_COMPONENT
+static struct proc_dir_entry *acpi_ac_dir;
+static struct proc_dir_entry *acpi_battery_dir;
+
+static DEFINE_MUTEX(cm_sbs_mutex);
+
+static int lock_ac_dir_cnt;
+static int lock_battery_dir_cnt;
+
+struct proc_dir_entry *acpi_lock_ac_dir(void)
+{
+       mutex_lock(&cm_sbs_mutex);
+       if (!acpi_ac_dir)
+               acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir);
+       if (acpi_ac_dir) {
+               lock_ac_dir_cnt++;
+       } else {
+               printk(KERN_ERR PREFIX
+                                 "Cannot create %s\n", ACPI_AC_CLASS);
+       }
+       mutex_unlock(&cm_sbs_mutex);
+       return acpi_ac_dir;
+}
+EXPORT_SYMBOL(acpi_lock_ac_dir);
+
+void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir_param)
+{
+       mutex_lock(&cm_sbs_mutex);
+       if (acpi_ac_dir_param)
+               lock_ac_dir_cnt--;
+       if (lock_ac_dir_cnt == 0 && acpi_ac_dir_param && acpi_ac_dir) {
+               remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
+               acpi_ac_dir = NULL;
+       }
+       mutex_unlock(&cm_sbs_mutex);
+}
+EXPORT_SYMBOL(acpi_unlock_ac_dir);
+
+struct proc_dir_entry *acpi_lock_battery_dir(void)
+{
+       mutex_lock(&cm_sbs_mutex);
+       if (!acpi_battery_dir) {
+               acpi_battery_dir =
+                   proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir);
+       }
+       if (acpi_battery_dir) {
+               lock_battery_dir_cnt++;
+       } else {
+               printk(KERN_ERR PREFIX
+                                 "Cannot create %s\n", ACPI_BATTERY_CLASS);
+       }
+       mutex_unlock(&cm_sbs_mutex);
+       return acpi_battery_dir;
+}
+EXPORT_SYMBOL(acpi_lock_battery_dir);
+
+void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir_param)
+{
+       mutex_lock(&cm_sbs_mutex);
+       if (acpi_battery_dir_param)
+               lock_battery_dir_cnt--;
+       if (lock_battery_dir_cnt == 0 && acpi_battery_dir_param
+           && acpi_battery_dir) {
+               remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
+               acpi_battery_dir = NULL;
+       }
+       mutex_unlock(&cm_sbs_mutex);
+       return;
+}
+EXPORT_SYMBOL(acpi_unlock_battery_dir);
index c1e31a41f94957d87ded390dfbfcc54333728e3c..25bbc55dca896889886a1e9ed856cfb6fa71135d 100644 (file)
@@ -1278,8 +1278,8 @@ static int __init acpi_thermal_init(void)
 
 static void __exit acpi_thermal_exit(void)
 {
-       destroy_workqueue(acpi_thermal_pm_queue);
        acpi_bus_unregister_driver(&acpi_thermal_driver);
+       destroy_workqueue(acpi_thermal_pm_queue);
 
        return;
 }
index 8b6990e417ec870d7c77e42c994b1e2245b3b88e..f8bc5a755dda411963e097cc41c27bec0752da71 100644 (file)
@@ -457,10 +457,10 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
        },
        {
         .callback = video_set_use_native_backlight,
-        .ident = "ThinkPad T430s",
+        .ident = "ThinkPad T430 and T430s",
         .matches = {
                DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-               DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430s"),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430"),
                },
        },
        {
@@ -472,7 +472,7 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
                },
        },
        {
-       .callback = video_set_use_native_backlight,
+        .callback = video_set_use_native_backlight,
        .ident = "ThinkPad X1 Carbon",
        .matches = {
                DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
@@ -500,7 +500,7 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
         .ident = "Dell Inspiron 7520",
         .matches = {
                DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-               DMI_MATCH(DMI_PRODUCT_VERSION, "Inspiron 7520"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7520"),
                },
        },
        {
@@ -511,6 +511,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
                DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5733Z"),
                },
        },
+       {
+        .callback = video_set_use_native_backlight,
+        .ident = "Acer Aspire 5742G",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5742G"),
+               },
+       },
        {
         .callback = video_set_use_native_backlight,
         .ident = "Acer Aspire V5-431",
index c2706047337f17c0fad38b3161cabc93d95be0e5..0033fafc470be5f7be9b84da74d689143abb5357 100644 (file)
@@ -815,7 +815,7 @@ config PATA_AT32
 
 config PATA_AT91
        tristate "PATA support for AT91SAM9260"
-       depends on ARM && ARCH_AT91
+       depends on ARM && SOC_AT91SAM9
        help
          This option enables support for IDE devices on the Atmel AT91SAM9260 SoC.
 
index 71e15b73513d22ed2bf5ac34afec9b5f42679fe7..60707814a84b19e2581d6309c2a17d4823d1e015 100644 (file)
@@ -1115,6 +1115,17 @@ static bool ahci_broken_online(struct pci_dev *pdev)
        return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
 }
 
+static bool ahci_broken_devslp(struct pci_dev *pdev)
+{
+       /* device with broken DEVSLP but still showing SDS capability */
+       static const struct pci_device_id ids[] = {
+               { PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */
+               {}
+       };
+
+       return pci_match_id(ids, pdev);
+}
+
 #ifdef CONFIG_ATA_ACPI
 static void ahci_gtf_filter_workaround(struct ata_host *host)
 {
@@ -1364,6 +1375,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
 
+       /* must set flag prior to save config in order to take effect */
+       if (ahci_broken_devslp(pdev))
+               hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
+
        /* save initial config */
        ahci_pci_save_initial_config(pdev, hpriv);
 
index b5eb886da22635c3c76775bc0ef6374af3464b98..af63c75c20011e10d76be66edb27d595cb47978c 100644 (file)
@@ -236,6 +236,7 @@ enum {
                                                        port start (wait until
                                                        error-handling stage) */
        AHCI_HFLAG_MULTI_MSI            = (1 << 16), /* multiple PCI MSIs */
+       AHCI_HFLAG_NO_DEVSLP            = (1 << 17), /* no device sleep */
 
        /* ap->flags bits */
 
index 497c7abe1c7df5ef79ccd246828b68a1251c5201..8befeb69eeb1133afc62daa43b1fb41af584994e 100644 (file)
 #include "ahci.h"
 
 enum {
-       PORT_PHY_CTL = 0x178,                   /* Port0 PHY Control */
-       PORT_PHY_CTL_PDDQ_LOC = 0x100000,       /* PORT_PHY_CTL bits */
-       HOST_TIMER1MS = 0xe0,                   /* Timer 1-ms */
+       /* Timer 1-ms Register */
+       IMX_TIMER1MS                            = 0x00e0,
+       /* Port0 PHY Control Register */
+       IMX_P0PHYCR                             = 0x0178,
+       IMX_P0PHYCR_TEST_PDDQ                   = 1 << 20,
+       IMX_P0PHYCR_CR_READ                     = 1 << 19,
+       IMX_P0PHYCR_CR_WRITE                    = 1 << 18,
+       IMX_P0PHYCR_CR_CAP_DATA                 = 1 << 17,
+       IMX_P0PHYCR_CR_CAP_ADDR                 = 1 << 16,
+       /* Port0 PHY Status Register */
+       IMX_P0PHYSR                             = 0x017c,
+       IMX_P0PHYSR_CR_ACK                      = 1 << 18,
+       IMX_P0PHYSR_CR_DATA_OUT                 = 0xffff << 0,
+       /* Lane0 Output Status Register */
+       IMX_LANE0_OUT_STAT                      = 0x2003,
+       IMX_LANE0_OUT_STAT_RX_PLL_STATE         = 1 << 1,
+       /* Clock Reset Register */
+       IMX_CLOCK_RESET                         = 0x7f3f,
+       IMX_CLOCK_RESET_RESET                   = 1 << 0,
 };
 
 enum ahci_imx_type {
@@ -54,9 +70,149 @@ MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support
 
 static void ahci_imx_host_stop(struct ata_host *host);
 
+static int imx_phy_crbit_assert(void __iomem *mmio, u32 bit, bool assert)
+{
+       int timeout = 10;
+       u32 crval;
+       u32 srval;
+
+       /* Assert or deassert the bit */
+       crval = readl(mmio + IMX_P0PHYCR);
+       if (assert)
+               crval |= bit;
+       else
+               crval &= ~bit;
+       writel(crval, mmio + IMX_P0PHYCR);
+
+       /* Wait for the cr_ack signal */
+       do {
+               srval = readl(mmio + IMX_P0PHYSR);
+               if ((assert ? srval : ~srval) & IMX_P0PHYSR_CR_ACK)
+                       break;
+               usleep_range(100, 200);
+       } while (--timeout);
+
+       return timeout ? 0 : -ETIMEDOUT;
+}
+
+static int imx_phy_reg_addressing(u16 addr, void __iomem *mmio)
+{
+       u32 crval = addr;
+       int ret;
+
+       /* Supply the address on cr_data_in */
+       writel(crval, mmio + IMX_P0PHYCR);
+
+       /* Assert the cr_cap_addr signal */
+       ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_ADDR, true);
+       if (ret)
+               return ret;
+
+       /* Deassert cr_cap_addr */
+       ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_ADDR, false);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int imx_phy_reg_write(u16 val, void __iomem *mmio)
+{
+       u32 crval = val;
+       int ret;
+
+       /* Supply the data on cr_data_in */
+       writel(crval, mmio + IMX_P0PHYCR);
+
+       /* Assert the cr_cap_data signal */
+       ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_DATA, true);
+       if (ret)
+               return ret;
+
+       /* Deassert cr_cap_data */
+       ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_DATA, false);
+       if (ret)
+               return ret;
+
+       if (val & IMX_CLOCK_RESET_RESET) {
+               /*
+                * In case we're resetting the phy, it's unable to acknowledge,
+                * so we return immediately here.
+                */
+               crval |= IMX_P0PHYCR_CR_WRITE;
+               writel(crval, mmio + IMX_P0PHYCR);
+               goto out;
+       }
+
+       /* Assert the cr_write signal */
+       ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_WRITE, true);
+       if (ret)
+               return ret;
+
+       /* Deassert cr_write */
+       ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_WRITE, false);
+       if (ret)
+               return ret;
+
+out:
+       return 0;
+}
+
+static int imx_phy_reg_read(u16 *val, void __iomem *mmio)
+{
+       int ret;
+
+       /* Assert the cr_read signal */
+       ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_READ, true);
+       if (ret)
+               return ret;
+
+       /* Capture the data from cr_data_out[] */
+       *val = readl(mmio + IMX_P0PHYSR) & IMX_P0PHYSR_CR_DATA_OUT;
+
+       /* Deassert cr_read */
+       ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_READ, false);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int imx_sata_phy_reset(struct ahci_host_priv *hpriv)
+{
+       void __iomem *mmio = hpriv->mmio;
+       int timeout = 10;
+       u16 val;
+       int ret;
+
+       /* Reset SATA PHY by setting RESET bit of PHY register CLOCK_RESET */
+       ret = imx_phy_reg_addressing(IMX_CLOCK_RESET, mmio);
+       if (ret)
+               return ret;
+       ret = imx_phy_reg_write(IMX_CLOCK_RESET_RESET, mmio);
+       if (ret)
+               return ret;
+
+       /* Wait for PHY RX_PLL to be stable */
+       do {
+               usleep_range(100, 200);
+               ret = imx_phy_reg_addressing(IMX_LANE0_OUT_STAT, mmio);
+               if (ret)
+                       return ret;
+               ret = imx_phy_reg_read(&val, mmio);
+               if (ret)
+                       return ret;
+               if (val & IMX_LANE0_OUT_STAT_RX_PLL_STATE)
+                       break;
+       } while (--timeout);
+
+       return timeout ? 0 : -ETIMEDOUT;
+}
+
 static int imx_sata_enable(struct ahci_host_priv *hpriv)
 {
        struct imx_ahci_priv *imxpriv = hpriv->plat_data;
+       struct device *dev = &imxpriv->ahci_pdev->dev;
        int ret;
 
        if (imxpriv->no_device)
@@ -101,6 +257,14 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv)
                regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
                                   IMX6Q_GPR13_SATA_MPLL_CLK_EN,
                                   IMX6Q_GPR13_SATA_MPLL_CLK_EN);
+
+               usleep_range(100, 200);
+
+               ret = imx_sata_phy_reset(hpriv);
+               if (ret) {
+                       dev_err(dev, "failed to reset phy: %d\n", ret);
+                       goto disable_regulator;
+               }
        }
 
        usleep_range(1000, 2000);
@@ -156,8 +320,8 @@ static void ahci_imx_error_handler(struct ata_port *ap)
         * without full reset once the pddq mode is enabled making it
         * impossible to use as part of libata LPM.
         */
-       reg_val = readl(mmio + PORT_PHY_CTL);
-       writel(reg_val | PORT_PHY_CTL_PDDQ_LOC, mmio + PORT_PHY_CTL);
+       reg_val = readl(mmio + IMX_P0PHYCR);
+       writel(reg_val | IMX_P0PHYCR_TEST_PDDQ, mmio + IMX_P0PHYCR);
        imx_sata_disable(hpriv);
        imxpriv->no_device = true;
 }
@@ -217,6 +381,7 @@ static int imx_ahci_probe(struct platform_device *pdev)
        if (!imxpriv)
                return -ENOMEM;
 
+       imxpriv->ahci_pdev = pdev;
        imxpriv->no_device = false;
        imxpriv->first_time = true;
        imxpriv->type = (enum ahci_imx_type)of_id->data;
@@ -248,7 +413,7 @@ static int imx_ahci_probe(struct platform_device *pdev)
 
        /*
         * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL,
-        * and IP vendor specific register HOST_TIMER1MS.
+        * and IP vendor specific register IMX_TIMER1MS.
         * Configure CAP_SSS (support stagered spin up).
         * Implement the port0.
         * Get the ahb clock rate, and configure the TIMER1MS register.
@@ -265,7 +430,7 @@ static int imx_ahci_probe(struct platform_device *pdev)
        }
 
        reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
-       writel(reg_val, hpriv->mmio + HOST_TIMER1MS);
+       writel(reg_val, hpriv->mmio + IMX_TIMER1MS);
 
        ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info, 0, 0);
        if (ret)
index 6bd4f660b4e15966ca2c351b4501c0521491de32..b9861453fc8148612a740418f5fee3088d7b65a1 100644 (file)
@@ -452,6 +452,13 @@ void ahci_save_initial_config(struct device *dev,
                cap &= ~HOST_CAP_SNTF;
        }
 
+       if ((cap2 & HOST_CAP2_SDS) && (hpriv->flags & AHCI_HFLAG_NO_DEVSLP)) {
+               dev_info(dev,
+                        "controller can't do DEVSLP, turning off\n");
+               cap2 &= ~HOST_CAP2_SDS;
+               cap2 &= ~HOST_CAP2_SADM;
+       }
+
        if (!(cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_YES_FBS)) {
                dev_info(dev, "controller can do FBS, turning on CAP_FBS\n");
                cap |= HOST_CAP_FBS;
index 943cc8b83e59bb7f1b293abce887be717047ffff..ea83828bfea94b41eae6947cfbbbaa8dfbc15b5a 100644 (file)
@@ -6314,6 +6314,8 @@ int ata_host_activate(struct ata_host *host, int irq,
 static void ata_port_detach(struct ata_port *ap)
 {
        unsigned long flags;
+       struct ata_link *link;
+       struct ata_device *dev;
 
        if (!ap->ops->error_handler)
                goto skip_eh;
@@ -6333,6 +6335,13 @@ static void ata_port_detach(struct ata_port *ap)
        cancel_delayed_work_sync(&ap->hotplug_task);
 
  skip_eh:
+       /* clean up zpodd on port removal */
+       ata_for_each_link(link, ap, HOST_FIRST) {
+               ata_for_each_dev(dev, link, ALL) {
+                       if (zpodd_dev_enabled(dev))
+                               zpodd_exit(dev);
+               }
+       }
        if (ap->pmp_link) {
                int i;
                for (i = 0; i < SATA_PMP_MAX_PORTS; i++)
index 96b629e1f0c9b0d887187b9a529ecee2c19d9945..cfa64bdf01c96ec41ad1b65917211524e0be8bf8 100644 (file)
@@ -1952,7 +1952,7 @@ static int __init atari_floppy_init (void)
                goto Enomem;
        }
        TrackBuffer = DMABuffer + 512;
-       PhysDMABuffer = virt_to_phys(DMABuffer);
+       PhysDMABuffer = atari_stram_to_phys(DMABuffer);
        PhysTrackBuffer = virt_to_phys(TrackBuffer);
        BufferDrive = BufferSide = BufferTrack = -1;
 
index 8f5565bf34cda31504e526ccc3d79d4e7fe20fd2..fa9bb742df6e0becfa8bca52576f17b5bdafe2bf 100644 (file)
@@ -3067,7 +3067,10 @@ static int raw_cmd_copyout(int cmd, void __user *param,
        int ret;
 
        while (ptr) {
-               ret = copy_to_user(param, ptr, sizeof(*ptr));
+               struct floppy_raw_cmd cmd = *ptr;
+               cmd.next = NULL;
+               cmd.kernel_data = NULL;
+               ret = copy_to_user(param, &cmd, sizeof(cmd));
                if (ret)
                        return -EFAULT;
                param += sizeof(struct floppy_raw_cmd);
@@ -3121,10 +3124,11 @@ loop:
                return -ENOMEM;
        *rcmd = ptr;
        ret = copy_from_user(ptr, param, sizeof(*ptr));
-       if (ret)
-               return -EFAULT;
        ptr->next = NULL;
        ptr->buffer_length = 0;
+       ptr->kernel_data = NULL;
+       if (ret)
+               return -EFAULT;
        param += sizeof(struct floppy_raw_cmd);
        if (ptr->cmd_count > 33)
                        /* the command may now also take up the space
@@ -3140,7 +3144,6 @@ loop:
        for (i = 0; i < 16; i++)
                ptr->reply[i] = 0;
        ptr->resultcode = 0;
-       ptr->kernel_data = NULL;
 
        if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
                if (ptr->length <= 0)
index 6d8a87f252de563f1251872e5bccbd25e2e64cf7..cb9b1f8326c3c6e1327b2c4505bc94aa143cf215 100644 (file)
@@ -144,11 +144,11 @@ static void virtblk_done(struct virtqueue *vq)
                if (unlikely(virtqueue_is_broken(vq)))
                        break;
        } while (!virtqueue_enable_cb(vq));
-       spin_unlock_irqrestore(&vblk->vq_lock, flags);
 
        /* In case queue is stopped waiting for more buffers. */
        if (req_done)
                blk_mq_start_stopped_hw_queues(vblk->disk->queue);
+       spin_unlock_irqrestore(&vblk->vq_lock, flags);
 }
 
 static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req)
@@ -202,8 +202,8 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req)
        err = __virtblk_add_req(vblk->vq, vbr, vbr->sg, num);
        if (err) {
                virtqueue_kick(vblk->vq);
-               spin_unlock_irqrestore(&vblk->vq_lock, flags);
                blk_mq_stop_hw_queue(hctx);
+               spin_unlock_irqrestore(&vblk->vq_lock, flags);
                /* Out of mem doesn't actually happen, since we fall back
                 * to direct descriptors */
                if (err == -ENOMEM || err == -ENOSPC)
index be571fef185da6a597fcdac3d15093ed8e47fb5b..a83b57e57b6370572d53325638355a0d94ce24bf 100644 (file)
@@ -82,6 +82,7 @@ static const struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x04CA, 0x3004) },
        { USB_DEVICE(0x04CA, 0x3005) },
        { USB_DEVICE(0x04CA, 0x3006) },
+       { USB_DEVICE(0x04CA, 0x3007) },
        { USB_DEVICE(0x04CA, 0x3008) },
        { USB_DEVICE(0x04CA, 0x300b) },
        { USB_DEVICE(0x0930, 0x0219) },
@@ -131,6 +132,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
        { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
index f338b0c5a8de507a153b6761886b943c702176a4..a7dfbf9a3afb6be53e372f78d9ee8202bdb17d08 100644 (file)
@@ -152,6 +152,7 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
@@ -1485,10 +1486,8 @@ static int btusb_probe(struct usb_interface *intf,
        if (id->driver_info & BTUSB_BCM92035)
                hdev->setup = btusb_setup_bcm92035;
 
-       if (id->driver_info & BTUSB_INTEL) {
-               usb_enable_autosuspend(data->udev);
+       if (id->driver_info & BTUSB_INTEL)
                hdev->setup = btusb_setup_intel;
-       }
 
        /* Interface numbers are hardcoded in the specification */
        data->isoc = usb_ifnum_to_if(data->udev, 1);
index 293e2e0a0a87c7d9877c27524fd98503ba16c1cf..00b73448b22ea7b77a55785cfbbddf022bf4bfd3 100644 (file)
@@ -56,6 +56,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/debugfs.h>
+#include <linux/log2.h>
 
 /*
  * DDR target is the same on all platforms.
@@ -222,12 +223,6 @@ static int mvebu_mbus_window_conflicts(struct mvebu_mbus_state *mbus,
                 */
                if ((u64)base < wend && end > wbase)
                        return 0;
-
-               /*
-                * Check if target/attribute conflicts
-                */
-               if (target == wtarget && attr == wattr)
-                       return 0;
        }
 
        return 1;
@@ -266,6 +261,17 @@ static int mvebu_mbus_setup_window(struct mvebu_mbus_state *mbus,
                mbus->soc->win_cfg_offset(win);
        u32 ctrl, remap_addr;
 
+       if (!is_power_of_2(size)) {
+               WARN(true, "Invalid MBus window size: 0x%zx\n", size);
+               return -EINVAL;
+       }
+
+       if ((base & (phys_addr_t)(size - 1)) != 0) {
+               WARN(true, "Invalid MBus base/size: %pa len 0x%zx\n", &base,
+                    size);
+               return -EINVAL;
+       }
+
        ctrl = ((size - 1) & WIN_CTRL_SIZE_MASK) |
                (attr << WIN_CTRL_ATTR_SHIFT)    |
                (target << WIN_CTRL_TGT_SHIFT)   |
@@ -413,6 +419,10 @@ static int mvebu_devs_debug_show(struct seq_file *seq, void *v)
                           win, (unsigned long long)wbase,
                           (unsigned long long)(wbase + wsize), wtarget, wattr);
 
+               if (!is_power_of_2(wsize) ||
+                   ((wbase & (u64)(wsize - 1)) != 0))
+                       seq_puts(seq, " (Invalid base/size!!)");
+
                if (win < mbus->soc->num_remappable_wins) {
                        seq_printf(seq, " (remap %016llx)\n",
                                   (unsigned long long)wremap);
index 8121b4c70edec77114e20295e195fa1d5f2cc797..b29703324e9431d24c5c0b588efbae14d8d2d5ba 100644 (file)
@@ -730,6 +730,7 @@ static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
 
        agp_copy_info(agp_bridge, &kerninfo);
 
+       memset(&userinfo, 0, sizeof(userinfo));
        userinfo.version.major = kerninfo.version.major;
        userinfo.version.minor = kerninfo.version.minor;
        userinfo.bridge_id = kerninfo.device->vendor |
index 6b75713d953a4e719cd33610f6034bec430c5d95..102c50d38902ca43fed85641618ba202a7251679 100644 (file)
@@ -995,8 +995,11 @@ retry:
                ibytes = min_t(size_t, ibytes, have_bytes - reserved);
        if (ibytes < min)
                ibytes = 0;
-       entropy_count = max_t(int, 0,
-                             entropy_count - (ibytes << (ENTROPY_SHIFT + 3)));
+       if (have_bytes >= ibytes + reserved)
+               entropy_count -= ibytes << (ENTROPY_SHIFT + 3);
+       else
+               entropy_count = reserved << (ENTROPY_SHIFT + 3);
+
        if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
                goto retry;
 
index b3ea223585bdeac64de19606f96b21b280c96210..61dcc8011ec711246727ce5c2750277f33c219f4 100644 (file)
@@ -328,13 +328,11 @@ int tpm_add_ppi(struct kobject *parent)
        /* Cache TPM ACPI handle and version string */
        acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
                            ppi_callback, NULL, NULL, &tpm_ppi_handle);
-       if (tpm_ppi_handle == NULL)
-               return -ENODEV;
-
-       return sysfs_create_group(parent, &ppi_attr_grp);
+       return tpm_ppi_handle ? sysfs_create_group(parent, &ppi_attr_grp) : 0;
 }
 
 void tpm_remove_ppi(struct kobject *parent)
 {
-       sysfs_remove_group(parent, &ppi_attr_grp);
+       if (tpm_ppi_handle)
+               sysfs_remove_group(parent, &ppi_attr_grp);
 }
index c7607feb18dd159b7626fd48340c764f50738c10..54a06526f64f09d7a49b8e043bd91d2e3d2dfffd 100644 (file)
@@ -27,7 +27,7 @@ LIST_HEAD(ccu_list);  /* The list of set up CCUs */
 
 static bool clk_requires_trigger(struct kona_clk *bcm_clk)
 {
-       struct peri_clk_data *peri = bcm_clk->peri;
+       struct peri_clk_data *peri = bcm_clk->u.peri;
        struct bcm_clk_sel *sel;
        struct bcm_clk_div *div;
 
@@ -63,7 +63,7 @@ static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk)
        u32 limit;
 
        BUG_ON(bcm_clk->type != bcm_clk_peri);
-       peri = bcm_clk->peri;
+       peri = bcm_clk->u.peri;
        name = bcm_clk->name;
        range = bcm_clk->ccu->range;
 
@@ -81,19 +81,19 @@ static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk)
 
        div = &peri->div;
        if (divider_exists(div)) {
-               if (div->offset > limit) {
+               if (div->u.s.offset > limit) {
                        pr_err("%s: bad divider offset for %s (%u > %u)\n",
-                               __func__, name, div->offset, limit);
+                               __func__, name, div->u.s.offset, limit);
                        return false;
                }
        }
 
        div = &peri->pre_div;
        if (divider_exists(div)) {
-               if (div->offset > limit) {
+               if (div->u.s.offset > limit) {
                        pr_err("%s: bad pre-divider offset for %s "
                                        "(%u > %u)\n",
-                               __func__, name, div->offset, limit);
+                               __func__, name, div->u.s.offset, limit);
                        return false;
                }
        }
@@ -249,21 +249,22 @@ static bool div_valid(struct bcm_clk_div *div, const char *field_name,
 {
        if (divider_is_fixed(div)) {
                /* Any fixed divider value but 0 is OK */
-               if (div->fixed == 0) {
+               if (div->u.fixed == 0) {
                        pr_err("%s: bad %s fixed value 0 for %s\n", __func__,
                                field_name, clock_name);
                        return false;
                }
                return true;
        }
-       if (!bitfield_valid(div->shift, div->width, field_name, clock_name))
+       if (!bitfield_valid(div->u.s.shift, div->u.s.width,
+                               field_name, clock_name))
                return false;
 
        if (divider_has_fraction(div))
-               if (div->frac_width > div->width) {
+               if (div->u.s.frac_width > div->u.s.width) {
                        pr_warn("%s: bad %s fraction width for %s (%u > %u)\n",
                                __func__, field_name, clock_name,
-                               div->frac_width, div->width);
+                               div->u.s.frac_width, div->u.s.width);
                        return false;
                }
 
@@ -278,7 +279,7 @@ static bool div_valid(struct bcm_clk_div *div, const char *field_name,
  */
 static bool kona_dividers_valid(struct kona_clk *bcm_clk)
 {
-       struct peri_clk_data *peri = bcm_clk->peri;
+       struct peri_clk_data *peri = bcm_clk->u.peri;
        struct bcm_clk_div *div;
        struct bcm_clk_div *pre_div;
        u32 limit;
@@ -295,7 +296,7 @@ static bool kona_dividers_valid(struct kona_clk *bcm_clk)
 
        limit = BITS_PER_BYTE * sizeof(u32);
 
-       return div->frac_width + pre_div->frac_width <= limit;
+       return div->u.s.frac_width + pre_div->u.s.frac_width <= limit;
 }
 
 
@@ -328,7 +329,7 @@ peri_clk_data_valid(struct kona_clk *bcm_clk)
        if (!peri_clk_data_offsets_valid(bcm_clk))
                return false;
 
-       peri = bcm_clk->peri;
+       peri = bcm_clk->u.peri;
        name = bcm_clk->name;
        gate = &peri->gate;
        if (gate_exists(gate) && !gate_valid(gate, "gate", name))
@@ -588,12 +589,12 @@ static void bcm_clk_teardown(struct kona_clk *bcm_clk)
 {
        switch (bcm_clk->type) {
        case bcm_clk_peri:
-               peri_clk_teardown(bcm_clk->data, &bcm_clk->init_data);
+               peri_clk_teardown(bcm_clk->u.data, &bcm_clk->init_data);
                break;
        default:
                break;
        }
-       bcm_clk->data = NULL;
+       bcm_clk->u.data = NULL;
        bcm_clk->type = bcm_clk_none;
 }
 
@@ -644,7 +645,7 @@ struct clk *kona_clk_setup(struct ccu_data *ccu, const char *name,
                break;
        }
        bcm_clk->type = type;
-       bcm_clk->data = data;
+       bcm_clk->u.data = data;
 
        /* Make sure everything makes sense before we set it up */
        if (!kona_clk_valid(bcm_clk)) {
index e3d339e08309f66ac61d2286c7c28bca9c4cec76..db11a87449f236c6bc1fcf4e5f6084750a1d4f3a 100644 (file)
@@ -61,7 +61,7 @@ u64 do_div_round_closest(u64 dividend, unsigned long divisor)
 /* Convert a divider into the scaled divisor value it represents. */
 static inline u64 scaled_div_value(struct bcm_clk_div *div, u32 reg_div)
 {
-       return (u64)reg_div + ((u64)1 << div->frac_width);
+       return (u64)reg_div + ((u64)1 << div->u.s.frac_width);
 }
 
 /*
@@ -77,7 +77,7 @@ u64 scaled_div_build(struct bcm_clk_div *div, u32 div_value, u32 billionths)
        BUG_ON(billionths >= BILLION);
 
        combined = (u64)div_value * BILLION + billionths;
-       combined <<= div->frac_width;
+       combined <<= div->u.s.frac_width;
 
        return do_div_round_closest(combined, BILLION);
 }
@@ -87,7 +87,7 @@ static inline u64
 scaled_div_min(struct bcm_clk_div *div)
 {
        if (divider_is_fixed(div))
-               return (u64)div->fixed;
+               return (u64)div->u.fixed;
 
        return scaled_div_value(div, 0);
 }
@@ -98,9 +98,9 @@ u64 scaled_div_max(struct bcm_clk_div *div)
        u32 reg_div;
 
        if (divider_is_fixed(div))
-               return (u64)div->fixed;
+               return (u64)div->u.fixed;
 
-       reg_div = ((u32)1 << div->width) - 1;
+       reg_div = ((u32)1 << div->u.s.width) - 1;
 
        return scaled_div_value(div, reg_div);
 }
@@ -115,7 +115,7 @@ divider(struct bcm_clk_div *div, u64 scaled_div)
        BUG_ON(scaled_div < scaled_div_min(div));
        BUG_ON(scaled_div > scaled_div_max(div));
 
-       return (u32)(scaled_div - ((u64)1 << div->frac_width));
+       return (u32)(scaled_div - ((u64)1 << div->u.s.frac_width));
 }
 
 /* Return a rate scaled for use when dividing by a scaled divisor. */
@@ -125,7 +125,7 @@ scale_rate(struct bcm_clk_div *div, u32 rate)
        if (divider_is_fixed(div))
                return (u64)rate;
 
-       return (u64)rate << div->frac_width;
+       return (u64)rate << div->u.s.frac_width;
 }
 
 /* CCU access */
@@ -398,14 +398,14 @@ static u64 divider_read_scaled(struct ccu_data *ccu, struct bcm_clk_div *div)
        u32 reg_div;
 
        if (divider_is_fixed(div))
-               return (u64)div->fixed;
+               return (u64)div->u.fixed;
 
        flags = ccu_lock(ccu);
-       reg_val = __ccu_read(ccu, div->offset);
+       reg_val = __ccu_read(ccu, div->u.s.offset);
        ccu_unlock(ccu, flags);
 
        /* Extract the full divider field from the register value */
-       reg_div = bitfield_extract(reg_val, div->shift, div->width);
+       reg_div = bitfield_extract(reg_val, div->u.s.shift, div->u.s.width);
 
        /* Return the scaled divisor value it represents */
        return scaled_div_value(div, reg_div);
@@ -433,16 +433,17 @@ static int __div_commit(struct ccu_data *ccu, struct bcm_clk_gate *gate,
         * state was defined in the device tree, we just find out
         * what its current value is rather than updating it.
         */
-       if (div->scaled_div == BAD_SCALED_DIV_VALUE) {
-               reg_val = __ccu_read(ccu, div->offset);
-               reg_div = bitfield_extract(reg_val, div->shift, div->width);
-               div->scaled_div = scaled_div_value(div, reg_div);
+       if (div->u.s.scaled_div == BAD_SCALED_DIV_VALUE) {
+               reg_val = __ccu_read(ccu, div->u.s.offset);
+               reg_div = bitfield_extract(reg_val, div->u.s.shift,
+                                               div->u.s.width);
+               div->u.s.scaled_div = scaled_div_value(div, reg_div);
 
                return 0;
        }
 
        /* Convert the scaled divisor to the value we need to record */
-       reg_div = divider(div, div->scaled_div);
+       reg_div = divider(div, div->u.s.scaled_div);
 
        /* Clock needs to be enabled before changing the rate */
        enabled = __is_clk_gate_enabled(ccu, gate);
@@ -452,9 +453,10 @@ static int __div_commit(struct ccu_data *ccu, struct bcm_clk_gate *gate,
        }
 
        /* Replace the divider value and record the result */
-       reg_val = __ccu_read(ccu, div->offset);
-       reg_val = bitfield_replace(reg_val, div->shift, div->width, reg_div);
-       __ccu_write(ccu, div->offset, reg_val);
+       reg_val = __ccu_read(ccu, div->u.s.offset);
+       reg_val = bitfield_replace(reg_val, div->u.s.shift, div->u.s.width,
+                                       reg_div);
+       __ccu_write(ccu, div->u.s.offset, reg_val);
 
        /* If the trigger fails we still want to disable the gate */
        if (!__clk_trigger(ccu, trig))
@@ -490,11 +492,11 @@ static int divider_write(struct ccu_data *ccu, struct bcm_clk_gate *gate,
 
        BUG_ON(divider_is_fixed(div));
 
-       previous = div->scaled_div;
+       previous = div->u.s.scaled_div;
        if (previous == scaled_div)
                return 0;       /* No change */
 
-       div->scaled_div = scaled_div;
+       div->u.s.scaled_div = scaled_div;
 
        flags = ccu_lock(ccu);
        __ccu_write_enable(ccu);
@@ -505,7 +507,7 @@ static int divider_write(struct ccu_data *ccu, struct bcm_clk_gate *gate,
        ccu_unlock(ccu, flags);
 
        if (ret)
-               div->scaled_div = previous;             /* Revert the change */
+               div->u.s.scaled_div = previous;         /* Revert the change */
 
        return ret;
 
@@ -802,7 +804,7 @@ static int selector_write(struct ccu_data *ccu, struct bcm_clk_gate *gate,
 static int kona_peri_clk_enable(struct clk_hw *hw)
 {
        struct kona_clk *bcm_clk = to_kona_clk(hw);
-       struct bcm_clk_gate *gate = &bcm_clk->peri->gate;
+       struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate;
 
        return clk_gate(bcm_clk->ccu, bcm_clk->name, gate, true);
 }
@@ -810,7 +812,7 @@ static int kona_peri_clk_enable(struct clk_hw *hw)
 static void kona_peri_clk_disable(struct clk_hw *hw)
 {
        struct kona_clk *bcm_clk = to_kona_clk(hw);
-       struct bcm_clk_gate *gate = &bcm_clk->peri->gate;
+       struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate;
 
        (void)clk_gate(bcm_clk->ccu, bcm_clk->name, gate, false);
 }
@@ -818,7 +820,7 @@ static void kona_peri_clk_disable(struct clk_hw *hw)
 static int kona_peri_clk_is_enabled(struct clk_hw *hw)
 {
        struct kona_clk *bcm_clk = to_kona_clk(hw);
-       struct bcm_clk_gate *gate = &bcm_clk->peri->gate;
+       struct bcm_clk_gate *gate = &bcm_clk->u.peri->gate;
 
        return is_clk_gate_enabled(bcm_clk->ccu, gate) ? 1 : 0;
 }
@@ -827,7 +829,7 @@ static unsigned long kona_peri_clk_recalc_rate(struct clk_hw *hw,
                        unsigned long parent_rate)
 {
        struct kona_clk *bcm_clk = to_kona_clk(hw);
-       struct peri_clk_data *data = bcm_clk->peri;
+       struct peri_clk_data *data = bcm_clk->u.peri;
 
        return clk_recalc_rate(bcm_clk->ccu, &data->div, &data->pre_div,
                                parent_rate);
@@ -837,20 +839,20 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate,
                        unsigned long *parent_rate)
 {
        struct kona_clk *bcm_clk = to_kona_clk(hw);
-       struct bcm_clk_div *div = &bcm_clk->peri->div;
+       struct bcm_clk_div *div = &bcm_clk->u.peri->div;
 
        if (!divider_exists(div))
                return __clk_get_rate(hw->clk);
 
        /* Quietly avoid a zero rate */
-       return round_rate(bcm_clk->ccu, div, &bcm_clk->peri->pre_div,
+       return round_rate(bcm_clk->ccu, div, &bcm_clk->u.peri->pre_div,
                                rate ? rate : 1, *parent_rate, NULL);
 }
 
 static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index)
 {
        struct kona_clk *bcm_clk = to_kona_clk(hw);
-       struct peri_clk_data *data = bcm_clk->peri;
+       struct peri_clk_data *data = bcm_clk->u.peri;
        struct bcm_clk_sel *sel = &data->sel;
        struct bcm_clk_trig *trig;
        int ret;
@@ -884,7 +886,7 @@ static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index)
 static u8 kona_peri_clk_get_parent(struct clk_hw *hw)
 {
        struct kona_clk *bcm_clk = to_kona_clk(hw);
-       struct peri_clk_data *data = bcm_clk->peri;
+       struct peri_clk_data *data = bcm_clk->u.peri;
        u8 index;
 
        index = selector_read_index(bcm_clk->ccu, &data->sel);
@@ -897,7 +899,7 @@ static int kona_peri_clk_set_rate(struct clk_hw *hw, unsigned long rate,
                        unsigned long parent_rate)
 {
        struct kona_clk *bcm_clk = to_kona_clk(hw);
-       struct peri_clk_data *data = bcm_clk->peri;
+       struct peri_clk_data *data = bcm_clk->u.peri;
        struct bcm_clk_div *div = &data->div;
        u64 scaled_div = 0;
        int ret;
@@ -958,7 +960,7 @@ struct clk_ops kona_peri_clk_ops = {
 static bool __peri_clk_init(struct kona_clk *bcm_clk)
 {
        struct ccu_data *ccu = bcm_clk->ccu;
-       struct peri_clk_data *peri = bcm_clk->peri;
+       struct peri_clk_data *peri = bcm_clk->u.peri;
        const char *name = bcm_clk->name;
        struct bcm_clk_trig *trig;
 
index 5e139adc3dc5909deee925ef38d2915894d52014..dee690951bb6c21677515039d5cac39770418414 100644 (file)
@@ -57,7 +57,7 @@
 #define divider_exists(div)            FLAG_TEST(div, DIV, EXISTS)
 #define divider_is_fixed(div)          FLAG_TEST(div, DIV, FIXED)
 #define divider_has_fraction(div)      (!divider_is_fixed(div) && \
-                                               (div)->frac_width > 0)
+                                               (div)->u.s.frac_width > 0)
 
 #define selector_exists(sel)           ((sel)->width != 0)
 #define trigger_exists(trig)           FLAG_TEST(trig, TRIG, EXISTS)
@@ -244,9 +244,9 @@ struct bcm_clk_div {
                        u32 frac_width; /* field fraction width */
 
                        u64 scaled_div; /* scaled divider value */
-               };
+               } s;
                u32 fixed;      /* non-zero fixed divider value */
-       };
+       } u;
        u32 flags;              /* BCM_CLK_DIV_FLAGS_* below */
 };
 
@@ -263,28 +263,28 @@ struct bcm_clk_div {
 /* A fixed (non-zero) divider */
 #define FIXED_DIVIDER(_value)                                          \
        {                                                               \
-               .fixed = (_value),                                      \
+               .u.fixed = (_value),                                    \
                .flags = FLAG(DIV, EXISTS)|FLAG(DIV, FIXED),            \
        }
 
 /* A divider with an integral divisor */
 #define DIVIDER(_offset, _shift, _width)                               \
        {                                                               \
-               .offset = (_offset),                                    \
-               .shift = (_shift),                                      \
-               .width = (_width),                                      \
-               .scaled_div = BAD_SCALED_DIV_VALUE,                     \
+               .u.s.offset = (_offset),                                \
+               .u.s.shift = (_shift),                                  \
+               .u.s.width = (_width),                                  \
+               .u.s.scaled_div = BAD_SCALED_DIV_VALUE,                 \
                .flags = FLAG(DIV, EXISTS),                             \
        }
 
 /* A divider whose divisor has an integer and fractional part */
 #define FRAC_DIVIDER(_offset, _shift, _width, _frac_width)             \
        {                                                               \
-               .offset = (_offset),                                    \
-               .shift = (_shift),                                      \
-               .width = (_width),                                      \
-               .frac_width = (_frac_width),                            \
-               .scaled_div = BAD_SCALED_DIV_VALUE,                     \
+               .u.s.offset = (_offset),                                \
+               .u.s.shift = (_shift),                                  \
+               .u.s.width = (_width),                                  \
+               .u.s.frac_width = (_frac_width),                        \
+               .u.s.scaled_div = BAD_SCALED_DIV_VALUE,                 \
                .flags = FLAG(DIV, EXISTS),                             \
        }
 
@@ -380,7 +380,7 @@ struct kona_clk {
        union {
                void *data;
                struct peri_clk_data *peri;
-       };
+       } u;
 };
 #define to_kona_clk(_hw) \
        container_of(_hw, struct kona_clk, hw)
index ec22112e569f7f3dc8f7c9477d0e3f99951e66c6..3fbee45402285c451ce88c35233a7eb352f53274 100644 (file)
@@ -144,6 +144,37 @@ static bool _is_valid_div(struct clk_divider *divider, unsigned int div)
        return true;
 }
 
+static int _round_up_table(const struct clk_div_table *table, int div)
+{
+       const struct clk_div_table *clkt;
+       int up = INT_MAX;
+
+       for (clkt = table; clkt->div; clkt++) {
+               if (clkt->div == div)
+                       return clkt->div;
+               else if (clkt->div < div)
+                       continue;
+
+               if ((clkt->div - div) < (up - div))
+                       up = clkt->div;
+       }
+
+       return up;
+}
+
+static int _div_round_up(struct clk_divider *divider,
+               unsigned long parent_rate, unsigned long rate)
+{
+       int div = DIV_ROUND_UP(parent_rate, rate);
+
+       if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+               div = __roundup_pow_of_two(div);
+       if (divider->table)
+               div = _round_up_table(divider->table, div);
+
+       return div;
+}
+
 static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
                unsigned long *best_parent_rate)
 {
@@ -159,7 +190,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
 
        if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
                parent_rate = *best_parent_rate;
-               bestdiv = DIV_ROUND_UP(parent_rate, rate);
+               bestdiv = _div_round_up(divider, parent_rate, rate);
                bestdiv = bestdiv == 0 ? 1 : bestdiv;
                bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
                return bestdiv;
@@ -219,6 +250,10 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
        u32 val;
 
        div = DIV_ROUND_UP(parent_rate, rate);
+
+       if (!_is_valid_div(divider, div))
+               return -EINVAL;
+
        value = _get_val(divider, div);
 
        if (value > div_mask(divider))
index dff0373f53c1fb1df1784366a28c35323cde17a5..7cf2c093cc54f28dbebd9482e43233a49daf02e3 100644 (file)
@@ -1984,9 +1984,28 @@ struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
 }
 EXPORT_SYMBOL_GPL(__clk_register);
 
-static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
+/**
+ * clk_register - allocate a new clock, register it and return an opaque cookie
+ * @dev: device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * clk_register is the primary interface for populating the clock tree with new
+ * clock nodes.  It returns a pointer to the newly allocated struct clk which
+ * cannot be dereferenced by driver code but may be used in conjuction with the
+ * rest of the clock API.  In the event of an error clk_register will return an
+ * error code; drivers must test for an error code after calling clk_register.
+ */
+struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 {
        int i, ret;
+       struct clk *clk;
+
+       clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+       if (!clk) {
+               pr_err("%s: could not allocate clk\n", __func__);
+               ret = -ENOMEM;
+               goto fail_out;
+       }
 
        clk->name = kstrdup(hw->init->name, GFP_KERNEL);
        if (!clk->name) {
@@ -2026,7 +2045,7 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
 
        ret = __clk_init(dev, clk);
        if (!ret)
-               return 0;
+               return clk;
 
 fail_parent_names_copy:
        while (--i >= 0)
@@ -2035,36 +2054,6 @@ fail_parent_names_copy:
 fail_parent_names:
        kfree(clk->name);
 fail_name:
-       return ret;
-}
-
-/**
- * clk_register - allocate a new clock, register it and return an opaque cookie
- * @dev: device that is registering this clock
- * @hw: link to hardware-specific clock data
- *
- * clk_register is the primary interface for populating the clock tree with new
- * clock nodes.  It returns a pointer to the newly allocated struct clk which
- * cannot be dereferenced by driver code but may be used in conjuction with the
- * rest of the clock API.  In the event of an error clk_register will return an
- * error code; drivers must test for an error code after calling clk_register.
- */
-struct clk *clk_register(struct device *dev, struct clk_hw *hw)
-{
-       int ret;
-       struct clk *clk;
-
-       clk = kzalloc(sizeof(*clk), GFP_KERNEL);
-       if (!clk) {
-               pr_err("%s: could not allocate clk\n", __func__);
-               ret = -ENOMEM;
-               goto fail_out;
-       }
-
-       ret = _clk_register(dev, hw, clk);
-       if (!ret)
-               return clk;
-
        kfree(clk);
 fail_out:
        return ERR_PTR(ret);
@@ -2151,9 +2140,10 @@ void clk_unregister(struct clk *clk)
 
        if (!hlist_empty(&clk->children)) {
                struct clk *child;
+               struct hlist_node *t;
 
                /* Reparent all children to the orphan list. */
-               hlist_for_each_entry(child, &clk->children, child_node)
+               hlist_for_each_entry_safe(child, t, &clk->children, child_node)
                        clk_set_parent(child, NULL);
        }
 
@@ -2173,7 +2163,7 @@ EXPORT_SYMBOL_GPL(clk_unregister);
 
 static void devm_clk_release(struct device *dev, void *res)
 {
-       clk_unregister(res);
+       clk_unregister(*(struct clk **)res);
 }
 
 /**
@@ -2188,18 +2178,18 @@ static void devm_clk_release(struct device *dev, void *res)
 struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw)
 {
        struct clk *clk;
-       int ret;
+       struct clk **clkp;
 
-       clk = devres_alloc(devm_clk_release, sizeof(*clk), GFP_KERNEL);
-       if (!clk)
+       clkp = devres_alloc(devm_clk_release, sizeof(*clkp), GFP_KERNEL);
+       if (!clkp)
                return ERR_PTR(-ENOMEM);
 
-       ret = _clk_register(dev, hw, clk);
-       if (!ret) {
-               devres_add(dev, clk);
+       clk = clk_register(dev, hw);
+       if (!IS_ERR(clk)) {
+               *clkp = clk;
+               devres_add(dev, clkp);
        } else {
-               devres_free(clk);
-               clk = ERR_PTR(ret);
+               devres_free(clkp);
        }
 
        return clk;
index 2e5810c88d1150874ece970fb64136a450ef64a6..1f6324e29a8099b09930f26234c703d7973be686 100644 (file)
@@ -156,6 +156,7 @@ cpg_mstp_clock_register(const char *name, const char *parent_name,
 static void __init cpg_mstp_clocks_init(struct device_node *np)
 {
        struct mstp_clock_group *group;
+       const char *idxname;
        struct clk **clks;
        unsigned int i;
 
@@ -184,6 +185,11 @@ static void __init cpg_mstp_clocks_init(struct device_node *np)
        for (i = 0; i < MSTP_MAX_CLOCKS; ++i)
                clks[i] = ERR_PTR(-ENOENT);
 
+       if (of_find_property(np, "clock-indices", &i))
+               idxname = "clock-indices";
+       else
+               idxname = "renesas,clock-indices";
+
        for (i = 0; i < MSTP_MAX_CLOCKS; ++i) {
                const char *parent_name;
                const char *name;
@@ -197,8 +203,7 @@ static void __init cpg_mstp_clocks_init(struct device_node *np)
                        continue;
 
                parent_name = of_clk_get_parent_name(np, i);
-               ret = of_property_read_u32_index(np, "renesas,clock-indices", i,
-                                                &clkidx);
+               ret = of_property_read_u32_index(np, idxname, i, &clkidx);
                if (parent_name == NULL || ret < 0)
                        break;
 
index 88dafb5e96270fa13923c5a95792c910a1bd00d4..de6da957a09d6ebe82f416370c84a7dc50acea8e 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 
 #include "clk.h"
 
@@ -43,6 +44,8 @@
 
 #define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
 
+void __iomem *clk_mgr_base_addr;
+
 static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
                                         unsigned long parent_rate)
 {
@@ -87,6 +90,7 @@ static __init struct clk *__socfpga_pll_init(struct device_node *node,
        const char *clk_name = node->name;
        const char *parent_name[SOCFPGA_MAX_PARENTS];
        struct clk_init_data init;
+       struct device_node *clkmgr_np;
        int rc;
        int i = 0;
 
@@ -96,6 +100,9 @@ static __init struct clk *__socfpga_pll_init(struct device_node *node,
        if (WARN_ON(!pll_clk))
                return NULL;
 
+       clkmgr_np = of_find_compatible_node(NULL, NULL, "altr,clk-mgr");
+       clk_mgr_base_addr = of_iomap(clkmgr_np, 0);
+       BUG_ON(!clk_mgr_base_addr);
        pll_clk->hw.reg = clk_mgr_base_addr + reg;
 
        of_property_read_string(node, "clock-output-names", &clk_name);
index 35a960a993f95c72b6247e52032c4184cbdd00b1..43db947e5f0e51e60c232832d379faca9ca386d3 100644 (file)
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-#include <linux/clk.h>
-#include <linux/clkdev.h>
-#include <linux/clk-provider.h>
-#include <linux/io.h>
 #include <linux/of.h>
-#include <linux/of_address.h>
 
 #include "clk.h"
 
-void __iomem *clk_mgr_base_addr;
-
-static const struct of_device_id socfpga_child_clocks[] __initconst = {
-       { .compatible = "altr,socfpga-pll-clock", socfpga_pll_init, },
-       { .compatible = "altr,socfpga-perip-clk", socfpga_periph_init, },
-       { .compatible = "altr,socfpga-gate-clk", socfpga_gate_init, },
-       {},
-};
-
-static void __init socfpga_clkmgr_init(struct device_node *node)
-{
-       clk_mgr_base_addr = of_iomap(node, 0);
-       of_clk_init(socfpga_child_clocks);
-}
-CLK_OF_DECLARE(socfpga_mgr, "altr,clk-mgr", socfpga_clkmgr_init);
+CLK_OF_DECLARE(socfpga_pll_clk, "altr,socfpga-pll-clock", socfpga_pll_init);
+CLK_OF_DECLARE(socfpga_perip_clk, "altr,socfpga-perip-clk", socfpga_periph_init);
+CLK_OF_DECLARE(socfpga_gate_clk, "altr,socfpga-gate-clk", socfpga_gate_init);
 
index bca0a0badbfa68c176aa0e82b663682b53845834..a886702f7c8ba3538ae410be65ba0061ec9d0d96 100644 (file)
@@ -521,8 +521,10 @@ static struct clk * __init clkgen_odf_register(const char *parent_name,
        gate->lock = odf_lock;
 
        div = kzalloc(sizeof(*div), GFP_KERNEL);
-       if (!div)
+       if (!div) {
+               kfree(gate);
                return ERR_PTR(-ENOMEM);
+       }
 
        div->flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
        div->reg = reg + pll_data->odf[odf].offset;
index 0d20241e07704df196c72ef22510775d22f5bfde..6aad8abc69a2d732c06a6e59a4f412859fba20aa 100644 (file)
@@ -58,9 +58,9 @@
 #define PLLDU_LFCON_SET_DIVN 600
 
 #define PLLE_BASE_DIVCML_SHIFT 24
-#define PLLE_BASE_DIVCML_WIDTH 4
+#define PLLE_BASE_DIVCML_MASK 0xf
 #define PLLE_BASE_DIVP_SHIFT 16
-#define PLLE_BASE_DIVP_WIDTH 7
+#define PLLE_BASE_DIVP_WIDTH 6
 #define PLLE_BASE_DIVN_SHIFT 8
 #define PLLE_BASE_DIVN_WIDTH 8
 #define PLLE_BASE_DIVM_SHIFT 0
 #define divp_mask(p) (p->params->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK :\
                      mask(p->params->div_nmp->divp_width))
 
+#define divm_shift(p) (p)->params->div_nmp->divm_shift
+#define divn_shift(p) (p)->params->div_nmp->divn_shift
+#define divp_shift(p) (p)->params->div_nmp->divp_shift
+
+#define divm_mask_shifted(p) (divm_mask(p) << divm_shift(p))
+#define divn_mask_shifted(p) (divn_mask(p) << divn_shift(p))
+#define divp_mask_shifted(p) (divp_mask(p) << divp_shift(p))
+
 #define divm_max(p) (divm_mask(p))
 #define divn_max(p) (divn_mask(p))
 #define divp_max(p) (1 << (divp_mask(p)))
@@ -476,13 +484,12 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll,
        } else {
                val = pll_readl_base(pll);
 
-               val &= ~((divm_mask(pll) << div_nmp->divm_shift) |
-                (divn_mask(pll) << div_nmp->divn_shift) |
-                (divp_mask(pll) << div_nmp->divp_shift));
+               val &= ~(divm_mask_shifted(pll) | divn_mask_shifted(pll) |
+                        divp_mask_shifted(pll));
 
-               val |= ((cfg->m << div_nmp->divm_shift) |
-                       (cfg->n << div_nmp->divn_shift) |
-                       (cfg->p << div_nmp->divp_shift));
+               val |= (cfg->m << divm_shift(pll)) |
+                      (cfg->n << divn_shift(pll)) |
+                      (cfg->p << divp_shift(pll));
 
                pll_writel_base(val, pll);
        }
@@ -730,11 +737,12 @@ static int clk_plle_enable(struct clk_hw *hw)
        if (pll->params->flags & TEGRA_PLLE_CONFIGURE) {
                /* configure dividers */
                val = pll_readl_base(pll);
-               val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
-               val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT);
-               val |= sel.m << pll->params->div_nmp->divm_shift;
-               val |= sel.n << pll->params->div_nmp->divn_shift;
-               val |= sel.p << pll->params->div_nmp->divp_shift;
+               val &= ~(divp_mask_shifted(pll) | divn_mask_shifted(pll) |
+                        divm_mask_shifted(pll));
+               val &= ~(PLLE_BASE_DIVCML_MASK << PLLE_BASE_DIVCML_SHIFT);
+               val |= sel.m << divm_shift(pll);
+               val |= sel.n << divn_shift(pll);
+               val |= sel.p << divp_shift(pll);
                val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
                pll_writel_base(val, pll);
        }
@@ -745,10 +753,11 @@ static int clk_plle_enable(struct clk_hw *hw)
        pll_writel_misc(val, pll);
 
        val = readl(pll->clk_base + PLLE_SS_CTRL);
+       val &= ~PLLE_SS_COEFFICIENTS_MASK;
        val |= PLLE_SS_DISABLE;
        writel(val, pll->clk_base + PLLE_SS_CTRL);
 
-       val |= pll_readl_base(pll);
+       val = pll_readl_base(pll);
        val |= (PLL_BASE_BYPASS | PLL_BASE_ENABLE);
        pll_writel_base(val, pll);
 
@@ -1292,10 +1301,11 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
        pll_writel(val, PLLE_SS_CTRL, pll);
 
        val = pll_readl_base(pll);
-       val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
-       val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT);
-       val |= sel.m << pll->params->div_nmp->divm_shift;
-       val |= sel.n << pll->params->div_nmp->divn_shift;
+       val &= ~(divp_mask_shifted(pll) | divn_mask_shifted(pll) |
+                divm_mask_shifted(pll));
+       val &= ~(PLLE_BASE_DIVCML_MASK << PLLE_BASE_DIVCML_SHIFT);
+       val |= sel.m << divm_shift(pll);
+       val |= sel.n << divn_shift(pll);
        val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
        pll_writel_base(val, pll);
        udelay(1);
@@ -1410,6 +1420,15 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
        return clk;
 }
 
+static struct div_nmp pll_e_nmp = {
+       .divn_shift = PLLE_BASE_DIVN_SHIFT,
+       .divn_width = PLLE_BASE_DIVN_WIDTH,
+       .divm_shift = PLLE_BASE_DIVM_SHIFT,
+       .divm_width = PLLE_BASE_DIVM_WIDTH,
+       .divp_shift = PLLE_BASE_DIVP_SHIFT,
+       .divp_width = PLLE_BASE_DIVP_WIDTH,
+};
+
 struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
                void __iomem *clk_base, void __iomem *pmc,
                unsigned long flags, struct tegra_clk_pll_params *pll_params,
@@ -1420,6 +1439,10 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
 
        pll_params->flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS;
        pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
+
+       if (!pll_params->div_nmp)
+               pll_params->div_nmp = &pll_e_nmp;
+
        pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
        if (IS_ERR(pll))
                return ERR_CAST(pll);
@@ -1557,9 +1580,8 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
                int m;
 
                m = _pll_fixed_mdiv(pll_params, parent_rate);
-               val = m << PLL_BASE_DIVM_SHIFT;
-               val |= (pll_params->vco_min / parent_rate)
-                               << PLL_BASE_DIVN_SHIFT;
+               val = m << divm_shift(pll);
+               val |= (pll_params->vco_min / parent_rate) << divn_shift(pll);
                pll_writel_base(val, pll);
        }
 
@@ -1718,7 +1740,7 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name,
                                        "pll_re_vco");
        } else {
                val_aux &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL);
-               pll_writel(val, pll_params->aux_reg, pll);
+               pll_writel(val_aux, pll_params->aux_reg, pll);
        }
 
        clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
index 00fdd11702849e042a2550dec0ac089075ada987..a8d7ea14f1835b3d8c6d45e20937051fd79f7cbb 100644 (file)
@@ -100,7 +100,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d)
                        || tcd->clkevt.mode == CLOCK_EVT_MODE_ONESHOT) {
                __raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR));
                __raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));
-               clk_disable_unprepare(tcd->clk);
+               clk_disable(tcd->clk);
        }
 
        switch (m) {
@@ -109,7 +109,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d)
         * of oneshot, we get lower overhead and improved accuracy.
         */
        case CLOCK_EVT_MODE_PERIODIC:
-               clk_prepare_enable(tcd->clk);
+               clk_enable(tcd->clk);
 
                /* slow clock, count up to RC, then irq and restart */
                __raw_writel(timer_clock
@@ -126,7 +126,7 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d)
                break;
 
        case CLOCK_EVT_MODE_ONESHOT:
-               clk_prepare_enable(tcd->clk);
+               clk_enable(tcd->clk);
 
                /* slow clock, count up to RC, then irq and stop */
                __raw_writel(timer_clock | ATMEL_TC_CPCSTOP
@@ -194,7 +194,7 @@ static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
        ret = clk_prepare_enable(t2_clk);
        if (ret)
                return ret;
-       clk_disable_unprepare(t2_clk);
+       clk_disable(t2_clk);
 
        clkevt.regs = tc->regs;
        clkevt.clk = t2_clk;
index b52e1c078b9955330dda32f803a26e8fa1527ab7..7f5374dbefd933d41ae5b64333d1cc8d9b52a6ce 100644 (file)
@@ -199,7 +199,7 @@ static int sirfsoc_local_timer_setup(struct clock_event_device *ce)
 
        action->dev_id = ce;
        BUG_ON(setup_irq(ce->irq, action));
-       irq_set_affinity(action->irq, cpumask_of(cpu));
+       irq_force_affinity(action->irq, cpumask_of(cpu));
 
        clockevents_register_device(ce);
        return 0;
index 148d707a1d439375ef36bf2ac8e6655fe2a61042..ccdd4c7e748b3b1e63b75e08398ac7972fde66b8 100644 (file)
@@ -369,7 +369,7 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg,
                return;
 
        /* Can only change if privileged. */
-       if (!capable(CAP_NET_ADMIN)) {
+       if (!__netlink_ns_capable(nsp, &init_user_ns, CAP_NET_ADMIN)) {
                err = EPERM;
                goto out;
        }
index 1bf6bbac3e03ae1bd9ffc4f001a71f7a0d0befcb..09b9129c7bd3b806cbacde8471ed574dd260ea25 100644 (file)
@@ -130,7 +130,7 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
                return -ENOENT;
        }
 
-       cpu_reg = devm_regulator_get_optional(cpu_dev, "cpu0");
+       cpu_reg = regulator_get_optional(cpu_dev, "cpu0");
        if (IS_ERR(cpu_reg)) {
                /*
                 * If cpu0 regulator supply node is present, but regulator is
@@ -145,23 +145,23 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
                        PTR_ERR(cpu_reg));
        }
 
-       cpu_clk = devm_clk_get(cpu_dev, NULL);
+       cpu_clk = clk_get(cpu_dev, NULL);
        if (IS_ERR(cpu_clk)) {
                ret = PTR_ERR(cpu_clk);
                pr_err("failed to get cpu0 clock: %d\n", ret);
-               goto out_put_node;
+               goto out_put_reg;
        }
 
        ret = of_init_opp_table(cpu_dev);
        if (ret) {
                pr_err("failed to init OPP table: %d\n", ret);
-               goto out_put_node;
+               goto out_put_clk;
        }
 
        ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
        if (ret) {
                pr_err("failed to init cpufreq table: %d\n", ret);
-               goto out_put_node;
+               goto out_put_clk;
        }
 
        of_property_read_u32(np, "voltage-tolerance", &voltage_tolerance);
@@ -216,6 +216,12 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
 
 out_free_table:
        dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
+out_put_clk:
+       if (!IS_ERR(cpu_clk))
+               clk_put(cpu_clk);
+out_put_reg:
+       if (!IS_ERR(cpu_reg))
+               regulator_put(cpu_reg);
 out_put_node:
        of_node_put(np);
        return ret;
index ba43991ba98aeeee2c7f833be6cb08f58638bb19..e1c6433b16e06653d159782b0a053830e570e3af 100644 (file)
@@ -366,6 +366,11 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                break;
 
        case CPUFREQ_GOV_LIMITS:
+               mutex_lock(&dbs_data->mutex);
+               if (!cpu_cdbs->cur_policy) {
+                       mutex_unlock(&dbs_data->mutex);
+                       break;
+               }
                mutex_lock(&cpu_cdbs->timer_mutex);
                if (policy->max < cpu_cdbs->cur_policy->cur)
                        __cpufreq_driver_target(cpu_cdbs->cur_policy,
@@ -375,6 +380,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                                        policy->min, CPUFREQ_RELATION_L);
                dbs_check_cpu(dbs_data, cpu);
                mutex_unlock(&cpu_cdbs->timer_mutex);
+               mutex_unlock(&dbs_data->mutex);
                break;
        }
        return 0;
index 099967302bf25939019875846f7819461a4805c2..eab8ccfe6bebed652b8fec4849a5fc9fb67d82f3 100644 (file)
@@ -37,6 +37,7 @@
 #define BYT_RATIOS             0x66a
 #define BYT_VIDS               0x66b
 #define BYT_TURBO_RATIOS       0x66c
+#define BYT_TURBO_VIDS         0x66d
 
 
 #define FRAC_BITS 6
@@ -70,8 +71,9 @@ struct pstate_data {
 };
 
 struct vid_data {
-       int32_t min;
-       int32_t max;
+       int min;
+       int max;
+       int turbo;
        int32_t ratio;
 };
 
@@ -359,14 +361,14 @@ static int byt_get_min_pstate(void)
 {
        u64 value;
        rdmsrl(BYT_RATIOS, value);
-       return (value >> 8) & 0xFF;
+       return (value >> 8) & 0x3F;
 }
 
 static int byt_get_max_pstate(void)
 {
        u64 value;
        rdmsrl(BYT_RATIOS, value);
-       return (value >> 16) & 0xFF;
+       return (value >> 16) & 0x3F;
 }
 
 static int byt_get_turbo_pstate(void)
@@ -393,6 +395,9 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate)
        vid_fp = clamp_t(int32_t, vid_fp, cpudata->vid.min, cpudata->vid.max);
        vid = fp_toint(vid_fp);
 
+       if (pstate > cpudata->pstate.max_pstate)
+               vid = cpudata->vid.turbo;
+
        val |= vid;
 
        wrmsrl(MSR_IA32_PERF_CTL, val);
@@ -402,13 +407,17 @@ static void byt_get_vid(struct cpudata *cpudata)
 {
        u64 value;
 
+
        rdmsrl(BYT_VIDS, value);
-       cpudata->vid.min = int_tofp((value >> 8) & 0x7f);
-       cpudata->vid.max = int_tofp((value >> 16) & 0x7f);
+       cpudata->vid.min = int_tofp((value >> 8) & 0x3f);
+       cpudata->vid.max = int_tofp((value >> 16) & 0x3f);
        cpudata->vid.ratio = div_fp(
                cpudata->vid.max - cpudata->vid.min,
                int_tofp(cpudata->pstate.max_pstate -
                        cpudata->pstate.min_pstate));
+
+       rdmsrl(BYT_TURBO_VIDS, value);
+       cpudata->vid.turbo = value & 0x7f;
 }
 
 
@@ -545,12 +554,7 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
 
        if (pstate_funcs.get_vid)
                pstate_funcs.get_vid(cpu);
-
-       /*
-        * goto max pstate so we don't slow up boot if we are built-in if we are
-        * a module we will take care of it during normal operation
-        */
-       intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate);
+       intel_pstate_set_pstate(cpu, cpu->pstate.min_pstate);
 }
 
 static inline void intel_pstate_calc_busy(struct cpudata *cpu,
@@ -695,11 +699,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
        cpu = all_cpu_data[cpunum];
 
        intel_pstate_get_cpu_pstates(cpu);
-       if (!cpu->pstate.current_pstate) {
-               all_cpu_data[cpunum] = NULL;
-               kfree(cpu);
-               return -ENODATA;
-       }
 
        cpu->cpu = cpunum;
 
@@ -710,7 +709,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
        cpu->timer.expires = jiffies + HZ/100;
        intel_pstate_busy_pid_reset(cpu);
        intel_pstate_sample(cpu);
-       intel_pstate_set_pstate(cpu, cpu->pstate.max_pstate);
 
        add_timer_on(&cpu->timer, cpunum);
 
index f0bc31f5db27a41db3d7f8556e72274b42a5eda5..d4add86219444af31891ef8c76013eaed0838282 100644 (file)
@@ -62,7 +62,7 @@ static int loongson2_cpufreq_target(struct cpufreq_policy *policy,
        set_cpus_allowed_ptr(current, &cpus_allowed);
 
        /* setting the cpu frequency */
-       clk_set_rate(policy->clk, freq);
+       clk_set_rate(policy->clk, freq * 1000);
 
        return 0;
 }
@@ -92,7 +92,7 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
             i++)
                loongson2_clockmod_table[i].frequency = (rate * i) / 8;
 
-       ret = clk_set_rate(cpuclk, rate);
+       ret = clk_set_rate(cpuclk, rate * 1000);
        if (ret) {
                clk_put(cpuclk);
                return ret;
index 9f25f5296029aeb0a22e0caf81bf35ca41b00063..0eabd81e1a902711bb838eb93dfed8e3289be610 100644 (file)
        char *tmp;                                              \
                                                                \
        tmp = kmalloc(sizeof(format) + max_alloc, GFP_ATOMIC);  \
-       sprintf(tmp, format, param);                            \
-       strcat(str, tmp);                                       \
-       kfree(tmp);                                             \
+       if (likely(tmp)) {                                      \
+               sprintf(tmp, format, param);                    \
+               strcat(str, tmp);                               \
+               kfree(tmp);                                     \
+       } else {                                                \
+               strcat(str, "kmalloc failure in SPRINTFCAT");   \
+       }                                                       \
 }
 
 static void report_jump_idx(u32 status, char *outstr)
index a886713937fd05b38fc10866bbce5266ac0bfae1..d5d30ed863ceb904c6e19e245b94d7ddba40f88f 100644 (file)
@@ -1009,6 +1009,7 @@ static void dmaengine_unmap(struct kref *kref)
                dma_unmap_page(dev, unmap->addr[i], unmap->len,
                               DMA_BIDIRECTIONAL);
        }
+       cnt = unmap->map_cnt;
        mempool_free(unmap, __get_unmap_pool(cnt)->pool);
 }
 
@@ -1074,6 +1075,7 @@ dmaengine_get_unmap_data(struct device *dev, int nr, gfp_t flags)
        memset(unmap, 0, sizeof(*unmap));
        kref_init(&unmap->kref);
        unmap->dev = dev;
+       unmap->map_cnt = nr;
 
        return unmap;
 }
index cfdbb92aae1dece5512f023afe341db2b086d171..7a740769c2fa592a0cbf7a73cdf2166e655e63d2 100644 (file)
@@ -1548,11 +1548,6 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata)
        /* Disable BLOCK interrupts as well */
        channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
 
-       err = devm_request_irq(chip->dev, chip->irq, dw_dma_interrupt,
-                              IRQF_SHARED, "dw_dmac", dw);
-       if (err)
-               return err;
-
        /* Create a pool of consistent memory blocks for hardware descriptors */
        dw->desc_pool = dmam_pool_create("dw_dmac_desc_pool", chip->dev,
                                         sizeof(struct dw_desc), 4, 0);
@@ -1563,6 +1558,11 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata)
 
        tasklet_init(&dw->tasklet, dw_dma_tasklet, (unsigned long)dw);
 
+       err = request_irq(chip->irq, dw_dma_interrupt, IRQF_SHARED,
+                         "dw_dmac", dw);
+       if (err)
+               return err;
+
        INIT_LIST_HEAD(&dw->dma.channels);
        for (i = 0; i < nr_channels; i++) {
                struct dw_dma_chan      *dwc = &dw->chan[i];
@@ -1667,6 +1667,7 @@ int dw_dma_remove(struct dw_dma_chip *chip)
        dw_dma_off(dw);
        dma_async_device_unregister(&dw->dma);
 
+       free_irq(chip->irq, dw);
        tasklet_kill(&dw->tasklet);
 
        list_for_each_entry_safe(dwc, _dwc, &dw->dma.channels,
index 766b68ed505c4d2b3964bfb1f0de6ab5ae1ff3a9..394cbc5c93e3600a8c918bfb673756bdd279ce7b 100644 (file)
@@ -191,12 +191,10 @@ static void mv_set_mode(struct mv_xor_chan *chan,
 
 static void mv_chan_activate(struct mv_xor_chan *chan)
 {
-       u32 activation;
-
        dev_dbg(mv_chan_to_devp(chan), " activate chan.\n");
-       activation = readl_relaxed(XOR_ACTIVATION(chan));
-       activation |= 0x1;
-       writel_relaxed(activation, XOR_ACTIVATION(chan));
+
+       /* writel ensures all descriptors are flushed before activation */
+       writel(BIT(0), XOR_ACTIVATION(chan));
 }
 
 static char mv_chan_is_busy(struct mv_xor_chan *chan)
index ab26d46bbe1598434625979abeb488d5199992d9..5ebdfbc1051ea7ed6e4dd948f9cac1e9b04760fc 100644 (file)
@@ -113,11 +113,9 @@ struct sa11x0_dma_phy {
        struct sa11x0_dma_desc  *txd_load;
        unsigned                sg_done;
        struct sa11x0_dma_desc  *txd_done;
-#ifdef CONFIG_PM_SLEEP
        u32                     dbs[2];
        u32                     dbt[2];
        u32                     dcsr;
-#endif
 };
 
 struct sa11x0_dma_dev {
@@ -984,7 +982,6 @@ static int sa11x0_dma_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
 static int sa11x0_dma_suspend(struct device *dev)
 {
        struct sa11x0_dma_dev *d = dev_get_drvdata(dev);
@@ -1054,7 +1051,6 @@ static int sa11x0_dma_resume(struct device *dev)
 
        return 0;
 }
-#endif
 
 static const struct dev_pm_ops sa11x0_dma_pm_ops = {
        .suspend_noirq = sa11x0_dma_suspend,
index c98764aeeec6112928fcde7ac0907949aab001ea..f477308b6e9ce23645784b3edc1bbd92b29b251d 100644 (file)
@@ -237,8 +237,8 @@ static inline bool is_next_generation(int new_generation, int old_generation)
 
 #define LOCAL_BUS 0xffc0
 
-/* arbitrarily chosen maximum range for physical DMA: 128 TB */
-#define FW_MAX_PHYSICAL_RANGE          (128ULL << 40)
+/* OHCI-1394's default upper bound for physical DMA: 4 GB */
+#define FW_MAX_PHYSICAL_RANGE          (1ULL << 32)
 
 void fw_core_handle_request(struct fw_card *card, struct fw_packet *request);
 void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);
index 8db66321956068701cde997e0bc25e167e781eb3..586f2f7f6993d350ca43fb0947bb0d457038d23f 100644 (file)
@@ -3716,7 +3716,7 @@ static int pci_probe(struct pci_dev *dev,
                    version >> 16, version & 0xff, ohci->card.index,
                    ohci->n_ir, ohci->n_it, ohci->quirks,
                    reg_read(ohci, OHCI1394_PhyUpperBound) ?
-                       ", >4 GB phys DMA" : "");
+                       ", physUB" : "");
 
        return 0;
 
index 3ee852c9925b6a1aa1887df101662194eeb3c42c..071c2c969eec06ad929ecfb871c614297a615e9e 100644 (file)
@@ -756,6 +756,7 @@ static const struct {
         */
        { ACPI_SIG_IBFT },
        { "iBFT" },
+       { "BIFT" },     /* Broadcom iSCSI Offload */
 };
 
 static void __init acpi_find_ibft_region(void)
index a86c49a605c63627b90d1def6fd8b038482ab005..4a1b5113e52778f895e2c31130b838da55fb7beb 100644 (file)
@@ -56,6 +56,7 @@ config GPIO_ACPI
        depends on ACPI
 
 config GPIOLIB_IRQCHIP
+       select IRQ_DOMAIN
        bool
 
 config DEBUG_GPIO
@@ -243,6 +244,15 @@ config GPIO_OCTEON
          Say yes here to support the on-chip GPIO lines on the OCTEON
          family of SOCs.
 
+config GPIO_OMAP
+       bool "TI OMAP GPIO support" if COMPILE_TEST && !ARCH_OMAP2PLUS
+       default y if ARCH_OMAP
+       depends on ARM
+       select GENERIC_IRQ_CHIP
+       select GPIOLIB_IRQCHIP
+       help
+         Say yes here to enable GPIO support for TI OMAP SoCs.
+
 config GPIO_PL061
        bool "PrimeCell PL061 GPIO support"
        depends on ARM_AMBA
@@ -259,7 +269,7 @@ config GPIO_PXA
 
 config GPIO_RCAR
        tristate "Renesas R-Car GPIO"
-       depends on ARM
+       depends on ARM && (ARCH_SHMOBILE || COMPILE_TEST)
        help
          Say yes here to support GPIO on Renesas R-Car SoCs.
 
@@ -510,6 +520,7 @@ config GPIO_PCA953X
 config GPIO_PCA953X_IRQ
        bool "Interrupt controller support for PCA953x"
        depends on GPIO_PCA953X=y
+       select GPIOLIB_IRQCHIP
        help
          Say yes here to enable the pca953x to be used as an interrupt
          controller. It requires the driver to be built in the kernel.
@@ -579,6 +590,7 @@ config GPIO_STP_XWAY
 config GPIO_TC3589X
        bool "TC3589X GPIOs"
        depends on MFD_TC3589X
+       select GPIOLIB_IRQCHIP
        help
          This enables support for the GPIOs found on the TC3589X
          I/O Expander.
@@ -699,13 +711,13 @@ config GPIO_AMD8111
 config GPIO_INTEL_MID
        bool "Intel Mid GPIO support"
        depends on PCI && X86
-       select IRQ_DOMAIN
+       select GPIOLIB_IRQCHIP
        help
          Say Y here to support Intel Mid GPIO.
 
 config GPIO_PCH
        tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7223/ML7831) GPIO"
-       depends on PCI && X86
+       depends on PCI && (X86_32 || COMPILE_TEST)
        select GENERIC_IRQ_CHIP
        help
          This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
@@ -739,7 +751,7 @@ config GPIO_SODAVILLE
 
 config GPIO_TIMBERDALE
        bool "Support for timberdale GPIO IP"
-       depends on MFD_TIMBERDALE && HAS_IOMEM
+       depends on MFD_TIMBERDALE
        ---help---
        Add support for the GPIO IP in the timberdale FPGA.
 
index 6309aff1d806be63acd3cf3b74e94221adf1e9ba..d10f6a9d875a2b626bc5a94a8d4bb83efef61a9f 100644 (file)
@@ -58,7 +58,7 @@ obj-$(CONFIG_GPIO_MVEBU)        += gpio-mvebu.o
 obj-$(CONFIG_GPIO_MXC)         += gpio-mxc.o
 obj-$(CONFIG_GPIO_MXS)         += gpio-mxs.o
 obj-$(CONFIG_GPIO_OCTEON)      += gpio-octeon.o
-obj-$(CONFIG_ARCH_OMAP)                += gpio-omap.o
+obj-$(CONFIG_GPIO_OMAP)                += gpio-omap.o
 obj-$(CONFIG_GPIO_PCA953X)     += gpio-pca953x.o
 obj-$(CONFIG_GPIO_PCF857X)     += gpio-pcf857x.o
 obj-$(CONFIG_GPIO_PCH)         += gpio-pch.o
index 307464fd015f4ceb6b733095663dd011eb73af3c..65978cf85f791cefbf494b9f2cfc694d9a3929ba 100644 (file)
@@ -51,6 +51,22 @@ struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
 }
 EXPORT_SYMBOL(devm_gpiod_get);
 
+/**
+ * devm_gpiod_get_optional - Resource-managed gpiod_get_optional()
+ * @dev: GPIO consumer
+ * @con_id: function within the GPIO consumer
+ *
+ * Managed gpiod_get_optional(). GPIO descriptors returned from this function
+ * are automatically disposed on driver detach. See gpiod_get_optional() for
+ * detailed information about behavior and return values.
+ */
+struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
+                                                      const char *con_id)
+{
+       return devm_gpiod_get_index_optional(dev, con_id, 0);
+}
+EXPORT_SYMBOL(devm_gpiod_get_optional);
+
 /**
  * devm_gpiod_get_index - Resource-managed gpiod_get_index()
  * @dev:       GPIO consumer
@@ -86,6 +102,33 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
 }
 EXPORT_SYMBOL(devm_gpiod_get_index);
 
+/**
+ * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()
+ * @dev: GPIO consumer
+ * @con_id: function within the GPIO consumer
+ * @index: index of the GPIO to obtain in the consumer
+ *
+ * Managed gpiod_get_index_optional(). GPIO descriptors returned from this
+ * function are automatically disposed on driver detach. See
+ * gpiod_get_index_optional() for detailed information about behavior and
+ * return values.
+ */
+struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev,
+                                                            const char *con_id,
+                                                            unsigned int index)
+{
+       struct gpio_desc *desc;
+
+       desc = devm_gpiod_get_index(dev, con_id, index);
+       if (IS_ERR(desc)) {
+               if (PTR_ERR(desc) == -ENOENT)
+                       return NULL;
+       }
+
+       return desc;
+}
+EXPORT_SYMBOL(devm_gpiod_get_index_optional);
+
 /**
  * devm_gpiod_put - Resource-managed gpiod_put()
  * @desc:      GPIO descriptor to dispose of
index 613265944e2e3966f57aa21447cd2093422d9ef5..f1ade8fa3218c346ddbe1867ba2242b146a94ec8 100644 (file)
@@ -106,10 +106,8 @@ static int adp5520_gpio_probe(struct platform_device *pdev)
        }
 
        dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
-       if (dev == NULL) {
-               dev_err(&pdev->dev, "failed to alloc memory\n");
+       if (dev == NULL)
                return -ENOMEM;
-       }
 
        dev->master = pdev->dev.parent;
 
index d974020b78bb2314dc0bf5d5e00f6048ccf561ff..ef19bc33f2bd3845cdc46b396e2f2949b36e15df 100644 (file)
@@ -379,10 +379,8 @@ static int adp5588_gpio_probe(struct i2c_client *client,
        }
 
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (dev == NULL) {
-               dev_err(&client->dev, "failed to alloc memory\n");
+       if (dev == NULL)
                return -ENOMEM;
-       }
 
        dev->client = client;
 
index ecb3ca2d1d102ab517c23be30b1d801874d7143d..6557147d9331e252d38c566a07b61ada3b7a7f71 100644 (file)
@@ -178,7 +178,7 @@ static int bt8xxgpio_probe(struct pci_dev *dev,
        struct bt8xxgpio *bg;
        int err;
 
-       bg = kzalloc(sizeof(*bg), GFP_KERNEL);
+       bg = devm_kzalloc(&dev->dev, sizeof(struct bt8xxgpio), GFP_KERNEL);
        if (!bg)
                return -ENOMEM;
 
@@ -188,9 +188,9 @@ static int bt8xxgpio_probe(struct pci_dev *dev,
        err = pci_enable_device(dev);
        if (err) {
                printk(KERN_ERR "bt8xxgpio: Can't enable device.\n");
-               goto err_freebg;
+               return err;
        }
-       if (!request_mem_region(pci_resource_start(dev, 0),
+       if (!devm_request_mem_region(&dev->dev, pci_resource_start(dev, 0),
                                pci_resource_len(dev, 0),
                                "bt8xxgpio")) {
                printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n",
@@ -201,11 +201,11 @@ static int bt8xxgpio_probe(struct pci_dev *dev,
        pci_set_master(dev);
        pci_set_drvdata(dev, bg);
 
-       bg->mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
+       bg->mmio = devm_ioremap(&dev->dev, pci_resource_start(dev, 0), 0x1000);
        if (!bg->mmio) {
                printk(KERN_ERR "bt8xxgpio: ioremap() failed\n");
                err = -EIO;
-               goto err_release_mem;
+               goto err_disable;
        }
 
        /* Disable interrupts */
@@ -220,18 +220,13 @@ static int bt8xxgpio_probe(struct pci_dev *dev,
        err = gpiochip_add(&bg->gpio);
        if (err) {
                printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n");
-               goto err_release_mem;
+               goto err_disable;
        }
 
        return 0;
 
-err_release_mem:
-       release_mem_region(pci_resource_start(dev, 0),
-                          pci_resource_len(dev, 0));
 err_disable:
        pci_disable_device(dev);
-err_freebg:
-       kfree(bg);
 
        return err;
 }
@@ -250,8 +245,6 @@ static void bt8xxgpio_remove(struct pci_dev *pdev)
        release_mem_region(pci_resource_start(pdev, 0),
                           pci_resource_len(pdev, 0));
        pci_disable_device(pdev);
-
-       kfree(bg);
 }
 
 #ifdef CONFIG_PM
index 339f9dac591bf0e28b85644d6538b3caec782818..9f0682534e2f46376a7086bc306cf195cc6e8e6f 100644 (file)
@@ -230,10 +230,8 @@ static int davinci_gpio_probe(struct platform_device *pdev)
        chips = devm_kzalloc(dev,
                             ngpio * sizeof(struct davinci_gpio_controller),
                             GFP_KERNEL);
-       if (!chips) {
-               dev_err(dev, "Memory allocation failed\n");
+       if (!chips)
                return -ENOMEM;
-       }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
index ed5711f77e2d056abe2a12c9eda5e9889980f090..cd3b814352748c3dd9786e0b2343f352d2188cd4 100644 (file)
@@ -198,6 +198,8 @@ static int dwapb_irq_set_type(struct irq_data *d, u32 type)
                break;
        }
 
+       irq_setup_alt_chip(d, type);
+
        writel(level, gpio->regs + GPIO_INTTYPE_LEVEL);
        writel(polarity, gpio->regs + GPIO_INT_POLARITY);
        spin_unlock_irqrestore(&bgc->lock, flags);
@@ -213,7 +215,7 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
        struct irq_chip_generic *irq_gc;
        unsigned int hwirq, ngpio = gc->ngpio;
        struct irq_chip_type *ct;
-       int err, irq;
+       int err, irq, i;
 
        irq = irq_of_parse_and_map(node, 0);
        if (!irq) {
@@ -227,7 +229,7 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
        if (!gpio->domain)
                return;
 
-       err = irq_alloc_domain_generic_chips(gpio->domain, ngpio, 1,
+       err = irq_alloc_domain_generic_chips(gpio->domain, ngpio, 2,
                                             "gpio-dwapb", handle_level_irq,
                                             IRQ_NOREQUEST, 0,
                                             IRQ_GC_INIT_NESTED_LOCK);
@@ -248,20 +250,24 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
        irq_gc->reg_base = gpio->regs;
        irq_gc->private = gpio;
 
-       ct = irq_gc->chip_types;
-       ct->chip.irq_ack = irq_gc_ack_set_bit;
-       ct->chip.irq_mask = irq_gc_mask_set_bit;
-       ct->chip.irq_unmask = irq_gc_mask_clr_bit;
-       ct->chip.irq_set_type = dwapb_irq_set_type;
-       ct->chip.irq_enable = dwapb_irq_enable;
-       ct->chip.irq_disable = dwapb_irq_disable;
-       ct->chip.irq_request_resources = dwapb_irq_reqres;
-       ct->chip.irq_release_resources = dwapb_irq_relres;
-       ct->regs.ack = GPIO_PORTA_EOI;
-       ct->regs.mask = GPIO_INTMASK;
-
-       irq_setup_generic_chip(irq_gc, IRQ_MSK(port->bgc.gc.ngpio),
-                       IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
+       for (i = 0; i < 2; i++) {
+               ct = &irq_gc->chip_types[i];
+               ct->chip.irq_ack = irq_gc_ack_set_bit;
+               ct->chip.irq_mask = irq_gc_mask_set_bit;
+               ct->chip.irq_unmask = irq_gc_mask_clr_bit;
+               ct->chip.irq_set_type = dwapb_irq_set_type;
+               ct->chip.irq_enable = dwapb_irq_enable;
+               ct->chip.irq_disable = dwapb_irq_disable;
+               ct->chip.irq_request_resources = dwapb_irq_reqres;
+               ct->chip.irq_release_resources = dwapb_irq_relres;
+               ct->regs.ack = GPIO_PORTA_EOI;
+               ct->regs.mask = GPIO_INTMASK;
+               ct->type = IRQ_TYPE_LEVEL_MASK;
+       }
+
+       irq_gc->chip_types[0].type = IRQ_TYPE_LEVEL_MASK;
+       irq_gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH;
+       irq_gc->chip_types[1].handler = handle_edge_irq;
 
        irq_set_chained_handler(irq, dwapb_irq_handler);
        irq_set_handler_data(irq, gpio);
index 8765bd6f48e12dd177de6a2e42ab2a8df8eecd7c..cde36054c3875dfed67706ee6e1bbbcb0b0179b9 100644 (file)
@@ -212,7 +212,7 @@ static void __em_gio_set(struct gpio_chip *chip, unsigned int reg,
 {
        /* upper 16 bits contains mask and lower 16 actual value */
        em_gio_write(gpio_to_priv(chip), reg,
-                    (1 << (shift + 16)) | (value << shift));
+                    (BIT(shift + 16)) | (value << shift));
 }
 
 static void em_gio_set(struct gpio_chip *chip, unsigned offset, int value)
@@ -284,7 +284,6 @@ static int em_gio_probe(struct platform_device *pdev)
 
        p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
        if (!p) {
-               dev_err(&pdev->dev, "failed to allocate driver data\n");
                ret = -ENOMEM;
                goto err0;
        }
index 80829f3c6543a2e0e24190a31c0f912ba15adc82..dcc2bb4074ef5db8dc2adc5a3cbfc8c331b0de3a 100644 (file)
@@ -344,37 +344,24 @@ static int ep93xx_gpio_probe(struct platform_device *pdev)
 {
        struct ep93xx_gpio *ep93xx_gpio;
        struct resource *res;
-       void __iomem *mmio;
        int i;
-       int ret;
+       struct device *dev = &pdev->dev;
 
-       ep93xx_gpio = kzalloc(sizeof(*ep93xx_gpio), GFP_KERNEL);
+       ep93xx_gpio = devm_kzalloc(dev, sizeof(struct ep93xx_gpio), GFP_KERNEL);
        if (!ep93xx_gpio)
                return -ENOMEM;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               ret = -ENXIO;
-               goto exit_free;
-       }
-
-       if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
-               ret = -EBUSY;
-               goto exit_free;
-       }
-
-       mmio = ioremap(res->start, resource_size(res));
-       if (!mmio) {
-               ret = -ENXIO;
-               goto exit_release;
-       }
-       ep93xx_gpio->mmio_base = mmio;
+       ep93xx_gpio->mmio_base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(ep93xx_gpio->mmio_base))
+               return PTR_ERR(ep93xx_gpio->mmio_base);
 
        for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) {
                struct bgpio_chip *bgc = &ep93xx_gpio->bgc[i];
                struct ep93xx_gpio_bank *bank = &ep93xx_gpio_banks[i];
 
-               if (ep93xx_gpio_add_bank(bgc, &pdev->dev, mmio, bank))
+               if (ep93xx_gpio_add_bank(bgc, &pdev->dev,
+                                        ep93xx_gpio->mmio_base, bank))
                        dev_warn(&pdev->dev, "Unable to add gpio bank %s\n",
                                bank->label);
        }
@@ -382,13 +369,6 @@ static int ep93xx_gpio_probe(struct platform_device *pdev)
        ep93xx_gpio_init_irq();
 
        return 0;
-
-exit_release:
-       release_mem_region(res->start, resource_size(res));
-exit_free:
-       kfree(ep93xx_gpio);
-       dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, ret);
-       return ret;
 }
 
 static struct platform_driver ep93xx_gpio_driver = {
index 7b95a4a8318c2bd43b0926521a39a2860f8f30ee..1237a73c3c911c341dae14924f6a37c15c0d65f3 100644 (file)
  */
 
 #include <linux/kernel.h>
-#include <linux/compiler.h>
-#include <linux/init.h>
 #include <linux/io.h>
-#include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/of_platform.h>
 #include <linux/of_gpio.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
 #include <linux/module.h>
 
 #define GEF_GPIO_DIRECT                0x00
 #define GEF_GPIO_OVERRUN       0x1C
 #define GEF_GPIO_MODE          0x20
 
-static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value)
+static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
+       struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
        unsigned int data;
 
-       data = ioread32be(reg);
-       /* value: 0=low; 1=high */
-       if (value & 0x1)
-               data = data | (0x1 << offset);
+       data = ioread32be(mmchip->regs + GEF_GPIO_OUT);
+       if (value)
+               data = data | BIT(offset);
        else
-               data = data & ~(0x1 << offset);
-
-       iowrite32be(data, reg);
+               data = data & ~BIT(offset);
+       iowrite32be(data, mmchip->regs + GEF_GPIO_OUT);
 }
 
-
 static int gef_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
 {
        unsigned int data;
        struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
 
        data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
-       data = data | (0x1 << offset);
+       data = data | BIT(offset);
        iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
 
        return 0;
@@ -71,11 +63,11 @@ static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
        unsigned int data;
        struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
 
-       /* Set direction before switching to input */
-       _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
+       /* Set value before switching to output */
+       gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
 
        data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
-       data = data & ~(0x1 << offset);
+       data = data & ~BIT(offset);
        iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
 
        return 0;
@@ -83,116 +75,56 @@ static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
 
 static int gef_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
-       unsigned int data;
-       int state = 0;
        struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
 
-       data = ioread32be(mmchip->regs + GEF_GPIO_IN);
-       state = (int)((data >> offset) & 0x1);
-
-       return state;
+       return !!(ioread32be(mmchip->regs + GEF_GPIO_IN) & BIT(offset));
 }
 
-static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
-
-       _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
-}
+static const struct of_device_id gef_gpio_ids[] = {
+       {
+               .compatible     = "gef,sbc610-gpio",
+               .data           = (void *)19,
+       }, {
+               .compatible     = "gef,sbc310-gpio",
+               .data           = (void *)6,
+       }, {
+               .compatible     = "ge,imp3a-gpio",
+               .data           = (void *)16,
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(of, gef_gpio_ids);
 
-static int __init gef_gpio_init(void)
+static int __init gef_gpio_probe(struct platform_device *pdev)
 {
-       struct device_node *np;
-       int retval;
-       struct of_mm_gpio_chip *gef_gpio_chip;
-
-       for_each_compatible_node(np, NULL, "gef,sbc610-gpio") {
-
-               pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
-
-               /* Allocate chip structure */
-               gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
-               if (!gef_gpio_chip) {
-                       pr_err("%s: Unable to allocate structure\n",
-                               np->full_name);
-                       continue;
-               }
-
-               /* Setup pointers to chip functions */
-               gef_gpio_chip->gc.of_gpio_n_cells = 2;
-               gef_gpio_chip->gc.ngpio = 19;
-               gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
-               gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
-               gef_gpio_chip->gc.get = gef_gpio_get;
-               gef_gpio_chip->gc.set = gef_gpio_set;
-
-               /* This function adds a memory mapped GPIO chip */
-               retval = of_mm_gpiochip_add(np, gef_gpio_chip);
-               if (retval) {
-                       kfree(gef_gpio_chip);
-                       pr_err("%s: Unable to add GPIO\n", np->full_name);
-               }
-       }
-
-       for_each_compatible_node(np, NULL, "gef,sbc310-gpio") {
-
-               pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
-
-               /* Allocate chip structure */
-               gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
-               if (!gef_gpio_chip) {
-                       pr_err("%s: Unable to allocate structure\n",
-                               np->full_name);
-                       continue;
-               }
-
-               /* Setup pointers to chip functions */
-               gef_gpio_chip->gc.of_gpio_n_cells = 2;
-               gef_gpio_chip->gc.ngpio = 6;
-               gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
-               gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
-               gef_gpio_chip->gc.get = gef_gpio_get;
-               gef_gpio_chip->gc.set = gef_gpio_set;
-
-               /* This function adds a memory mapped GPIO chip */
-               retval = of_mm_gpiochip_add(np, gef_gpio_chip);
-               if (retval) {
-                       kfree(gef_gpio_chip);
-                       pr_err("%s: Unable to add GPIO\n", np->full_name);
-               }
-       }
-
-       for_each_compatible_node(np, NULL, "ge,imp3a-gpio") {
-
-               pr_debug("%s: Initialising GE GPIO\n", np->full_name);
-
-               /* Allocate chip structure */
-               gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
-               if (!gef_gpio_chip) {
-                       pr_err("%s: Unable to allocate structure\n",
-                               np->full_name);
-                       continue;
-               }
-
-               /* Setup pointers to chip functions */
-               gef_gpio_chip->gc.of_gpio_n_cells = 2;
-               gef_gpio_chip->gc.ngpio = 16;
-               gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
-               gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
-               gef_gpio_chip->gc.get = gef_gpio_get;
-               gef_gpio_chip->gc.set = gef_gpio_set;
-
-               /* This function adds a memory mapped GPIO chip */
-               retval = of_mm_gpiochip_add(np, gef_gpio_chip);
-               if (retval) {
-                       kfree(gef_gpio_chip);
-                       pr_err("%s: Unable to add GPIO\n", np->full_name);
-               }
-       }
+       const struct of_device_id *of_id =
+               of_match_device(gef_gpio_ids, &pdev->dev);
+       struct of_mm_gpio_chip *mmchip;
+
+       mmchip = devm_kzalloc(&pdev->dev, sizeof(*mmchip), GFP_KERNEL);
+       if (!mmchip)
+               return -ENOMEM;
+
+       /* Setup pointers to chip functions */
+       mmchip->gc.ngpio = (u16)(uintptr_t)of_id->data;
+       mmchip->gc.of_gpio_n_cells = 2;
+       mmchip->gc.direction_input = gef_gpio_dir_in;
+       mmchip->gc.direction_output = gef_gpio_dir_out;
+       mmchip->gc.get = gef_gpio_get;
+       mmchip->gc.set = gef_gpio_set;
+
+       /* This function adds a memory mapped GPIO chip */
+       return of_mm_gpiochip_add(pdev->dev.of_node, mmchip);
+};
 
-       return 0;
+static struct platform_driver gef_gpio_driver = {
+       .driver = {
+               .name           = "gef-gpio",
+               .owner          = THIS_MODULE,
+               .of_match_table = gef_gpio_ids,
+       },
 };
-arch_initcall(gef_gpio_init);
+module_platform_driver_probe(gef_gpio_driver, gef_gpio_probe);
 
 MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
 MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
index b5dff9e742f846e65660ea046ebb6f402cca4763..fea8c82bb8fcc2a96bfb4135dbeed0845b46d517 100644 (file)
@@ -388,6 +388,14 @@ static int bgpio_setup_direction(struct bgpio_chip *bgc,
        return 0;
 }
 
+static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin)
+{
+       if (gpio_pin < chip->ngpio)
+               return 0;
+
+       return -EINVAL;
+}
+
 int bgpio_remove(struct bgpio_chip *bgc)
 {
        return gpiochip_remove(&bgc->gc);
@@ -413,6 +421,7 @@ int bgpio_init(struct bgpio_chip *bgc, struct device *dev,
        bgc->gc.label = dev_name(dev);
        bgc->gc.base = -1;
        bgc->gc.ngpio = bgc->bits;
+       bgc->gc.request = bgpio_request;
 
        ret = bgpio_setup_io(bgc, dat, set, clr);
        if (ret)
index 84d2478ec294cdb27be0a7f576b79bf335b6b124..3c3f515b7916b1a32b2c25a1845989df978a7f03 100644 (file)
@@ -481,7 +481,7 @@ out:
        return ret;
 }
 
-static struct of_device_id grgpio_match[] = {
+static const struct of_device_id grgpio_match[] = {
        {.name = "GAISLER_GPIO"},
        {.name = "01_01a"},
        {},
index e73c6755a5eb6b324d06f14f4a7cf574d025c8ca..70304220a479a9862f4f5709e6a9a88a785b487d 100644 (file)
@@ -305,6 +305,8 @@ static struct ichx_desc ich6_desc = {
 
        .ngpio = 50,
        .have_blink = true,
+       .regs = ichx_regs,
+       .reglen = ichx_reglen,
 };
 
 /* Intel 3100 */
@@ -324,6 +326,8 @@ static struct ichx_desc i3100_desc = {
        .uses_gpe0 = true,
 
        .ngpio = 50,
+       .regs = ichx_regs,
+       .reglen = ichx_reglen,
 };
 
 /* ICH7 and ICH8-based */
index 2ecd3a09c743e6dba7434c9cbfab0e5c70bc24c3..42852eaaf0200a43320ac946db793939e162ff50 100644 (file)
@@ -152,34 +152,21 @@ static int ttl_probe(struct platform_device *pdev)
        pdata = dev_get_platdata(&pdev->dev);
        if (!pdata) {
                dev_err(dev, "no platform data\n");
-               ret = -ENXIO;
-               goto out_return;
+               return -ENXIO;
        }
 
-       mod = kzalloc(sizeof(*mod), GFP_KERNEL);
-       if (!mod) {
-               dev_err(dev, "unable to allocate private data\n");
-               ret = -ENOMEM;
-               goto out_return;
-       }
+       mod = devm_kzalloc(dev, sizeof(*mod), GFP_KERNEL);
+       if (!mod)
+               return -ENOMEM;
 
        platform_set_drvdata(pdev, mod);
        spin_lock_init(&mod->lock);
 
        /* get access to the MODULbus registers for this module */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "MODULbus registers not found\n");
-               ret = -ENODEV;
-               goto out_free_mod;
-       }
-
-       mod->regs = ioremap(res->start, resource_size(res));
-       if (!mod->regs) {
-               dev_err(dev, "MODULbus registers not ioremap\n");
-               ret = -ENOMEM;
-               goto out_free_mod;
-       }
+       mod->regs = devm_ioremap_resource(dev, res);
+       if (IS_ERR(mod->regs))
+               return PTR_ERR(mod->regs);
 
        ttl_setup_device(mod);
 
@@ -198,17 +185,10 @@ static int ttl_probe(struct platform_device *pdev)
        ret = gpiochip_add(gpio);
        if (ret) {
                dev_err(dev, "unable to add GPIO chip\n");
-               goto out_iounmap_regs;
+               return ret;
        }
 
        return 0;
-
-out_iounmap_regs:
-       iounmap(mod->regs);
-out_free_mod:
-       kfree(mod);
-out_return:
-       return ret;
 }
 
 static int ttl_remove(struct platform_device *pdev)
@@ -223,8 +203,6 @@ static int ttl_remove(struct platform_device *pdev)
                return ret;
        }
 
-       iounmap(mod->regs);
-       kfree(mod);
        return 0;
 }
 
index c6d88173f5a2ab53f267987b0323550c1dc7bd33..1e5e51987d315fdce98f67d3c9f8db776fa83de6 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/mfd/kempld.h>
 
 #define KEMPLD_GPIO_MAX_NUM            16
-#define KEMPLD_GPIO_MASK(x)            (1 << ((x) % 8))
+#define KEMPLD_GPIO_MASK(x)            (BIT((x) % 8))
 #define KEMPLD_GPIO_DIR_NUM(x)         (0x40 + (x) / 8)
 #define KEMPLD_GPIO_LVL_NUM(x)         (0x42 + (x) / 8)
 #define KEMPLD_GPIO_EVT_LVL_EDGE       0x46
@@ -216,4 +216,4 @@ module_platform_driver(kempld_gpio_driver);
 MODULE_DESCRIPTION("KEM PLD GPIO Driver");
 MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:gpio-kempld");
+MODULE_ALIAS("platform:kempld-gpio");
index 9a82a9074a2cfb3a74a1c56592eaf680dee1fbef..2bea89b72508b8a54f7857c6ec3ca46e91c1c45e 100644 (file)
@@ -375,10 +375,8 @@ static int lp_gpio_probe(struct platform_device *pdev)
        int ret = -ENODEV;
 
        lg = devm_kzalloc(dev, sizeof(struct lp_gpio), GFP_KERNEL);
-       if (!lg) {
-               dev_err(dev, "can't allocate lp_gpio chip data\n");
+       if (!lg)
                return -ENOMEM;
-       }
 
        lg->pdev = pdev;
        platform_set_drvdata(pdev, lg);
index 8672755f95c915a2ae2977678c51e554f616ae3f..0814584fcdc1e1164850231cf0e951510bee57e6 100644 (file)
@@ -237,10 +237,9 @@ int __max730x_remove(struct device *dev)
        ts->write(dev, 0x04, 0x00);
 
        ret = gpiochip_remove(&ts->chip);
-       if (!ret) {
+       if (!ret)
                mutex_destroy(&ts->lock);
-               kfree(ts);
-       } else
+       else
                dev_err(dev, "Failed to remove GPIO controller: %d\n", ret);
 
        return ret;
index 99a68310e7c09eb053f5cd28395549ece9f8babe..fe7c0e211f9a85becb51bf64a808033c50203cee 100644 (file)
@@ -714,7 +714,7 @@ fail:
 
 #ifdef CONFIG_OF
 #ifdef CONFIG_SPI_MASTER
-static struct of_device_id mcp23s08_spi_of_match[] = {
+static const struct of_device_id mcp23s08_spi_of_match[] = {
        {
                .compatible = "microchip,mcp23s08",
                .data = (void *) MCP_TYPE_S08,
@@ -738,7 +738,7 @@ MODULE_DEVICE_TABLE(of, mcp23s08_spi_of_match);
 #endif
 
 #if IS_ENABLED(CONFIG_I2C)
-static struct of_device_id mcp23s08_i2c_of_match[] = {
+static const struct of_device_id mcp23s08_i2c_of_match[] = {
        {
                .compatible = "microchip,mcp23008",
                .data = (void *) MCP_TYPE_008,
@@ -867,7 +867,7 @@ static int mcp23s08_probe(struct spi_device *spi)
 {
        struct mcp23s08_platform_data   *pdata;
        unsigned                        addr;
-       unsigned                        chips = 0;
+       int                             chips = 0;
        struct mcp23s08_driver_data     *data;
        int                             status, type;
        unsigned                        base = -1,
@@ -895,8 +895,13 @@ static int mcp23s08_probe(struct spi_device *spi)
                        return -ENODEV;
                }
 
-               for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++)
+               for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
                        pullups[addr] = 0;
+                       if (spi_present_mask & (1 << addr))
+                               chips++;
+               }
+               if (!chips)
+                       return -ENODEV;
        } else {
                type = spi_get_device_id(spi)->driver_data;
                pdata = dev_get_platdata(&spi->dev);
@@ -919,12 +924,12 @@ static int mcp23s08_probe(struct spi_device *spi)
                        pullups[addr] = pdata->chip[addr].pullups;
                }
 
-               if (!chips)
-                       return -ENODEV;
-
                base = pdata->base;
        }
 
+       if (!chips)
+               return -ENODEV;
+
        data = kzalloc(sizeof(*data) + chips * sizeof(struct mcp23s08),
                        GFP_KERNEL);
        if (!data)
@@ -935,6 +940,10 @@ static int mcp23s08_probe(struct spi_device *spi)
                if (!(spi_present_mask & (1 << addr)))
                        continue;
                chips--;
+               if (chips < 0) {
+                       dev_err(&spi->dev, "FATAL: invalid negative chip id\n");
+                       goto fail;
+               }
                data->mcp[addr] = &data->chip[chips];
                status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi,
                                            0x40 | (addr << 1), type, base,
index ccd45704e5fdc1f5c4a089e9dd6f994c8eb10a67..4661e181be0481e65f6758919db714b2ca48e360 100644 (file)
@@ -113,10 +113,8 @@ static int moxart_gpio_probe(struct platform_device *pdev)
        int ret;
 
        mgc = devm_kzalloc(dev, sizeof(*mgc), GFP_KERNEL);
-       if (!mgc) {
-               dev_err(dev, "can't allocate GPIO chip container\n");
+       if (!mgc)
                return -ENOMEM;
-       }
        mgc->gpio = moxart_template_chip;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
index d425094223947b96c3f35c40fc9997155bab0274..418e386503632f360701b9e10696b48aba529fe1 100644 (file)
@@ -535,7 +535,7 @@ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 #define mvebu_gpio_dbg_show NULL
 #endif
 
-static struct of_device_id mvebu_gpio_of_match[] = {
+static const struct of_device_id mvebu_gpio_of_match[] = {
        {
                .compatible = "marvell,orion-gpio",
                .data       = (void *) MVEBU_GPIO_SOC_VARIANT_ORION,
@@ -574,10 +574,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
                soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION;
 
        mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), GFP_KERNEL);
-       if (!mvchip) {
-               dev_err(&pdev->dev, "Cannot allocate memory\n");
+       if (!mvchip)
                return -ENOMEM;
-       }
 
        if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {
                dev_err(&pdev->dev, "Missing ngpios OF property\n");
@@ -738,9 +736,4 @@ static struct platform_driver mvebu_gpio_driver = {
        },
        .probe          = mvebu_gpio_probe,
 };
-
-static int __init mvebu_gpio_init(void)
-{
-       return platform_driver_register(&mvebu_gpio_driver);
-}
-postcore_initcall(mvebu_gpio_init);
+module_platform_driver(mvebu_gpio_driver);
index 19b886c21b1dbe357a806100fc44cf4f480620d2..00f29aa1fb9dda1a981b3d8245af3b1b9f1232e2 100644 (file)
@@ -24,9 +24,9 @@
 #include <linux/pm.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/irqdomain.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/gpio.h>
+#include <linux/bitops.h>
 #include <linux/platform_data/gpio-omap.h>
 
 #define OFF_MODE       1
@@ -52,7 +52,6 @@ struct gpio_bank {
        struct list_head node;
        void __iomem *base;
        u16 irq;
-       struct irq_domain *domain;
        u32 non_wakeup_gpios;
        u32 enabled_non_wakeup_gpios;
        struct gpio_regs context;
@@ -84,22 +83,21 @@ struct gpio_bank {
 };
 
 #define GPIO_INDEX(bank, gpio) (gpio % bank->width)
-#define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio))
+#define GPIO_BIT(bank, gpio) (BIT(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))
+#define LINE_USED(line, offset) (line & (BIT(offset)))
 
 static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq)
 {
        return bank->chip.base + gpio_irq;
 }
 
-static int omap_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+static inline struct gpio_bank *_irq_data_get_bank(struct irq_data *d)
 {
-       struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
-
-       return irq_find_mapping(bank->domain, offset);
+       struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+       return container_of(chip, struct gpio_bank, chip);
 }
 
 static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
@@ -110,9 +108,9 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
        reg += bank->regs->direction;
        l = readl_relaxed(reg);
        if (is_input)
-               l |= 1 << gpio;
+               l |= BIT(gpio);
        else
-               l &= ~(1 << gpio);
+               l &= ~(BIT(gpio));
        writel_relaxed(l, reg);
        bank->context.oe = l;
 }
@@ -155,14 +153,14 @@ static int _get_gpio_datain(struct gpio_bank *bank, int offset)
 {
        void __iomem *reg = bank->base + bank->regs->datain;
 
-       return (readl_relaxed(reg) & (1 << offset)) != 0;
+       return (readl_relaxed(reg) & (BIT(offset))) != 0;
 }
 
 static int _get_gpio_dataout(struct gpio_bank *bank, int offset)
 {
        void __iomem *reg = bank->base + bank->regs->dataout;
 
-       return (readl_relaxed(reg) & (1 << offset)) != 0;
+       return (readl_relaxed(reg) & (BIT(offset))) != 0;
 }
 
 static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
@@ -180,7 +178,7 @@ static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
 static inline void _gpio_dbck_enable(struct gpio_bank *bank)
 {
        if (bank->dbck_enable_mask && !bank->dbck_enabled) {
-               clk_enable(bank->dbck);
+               clk_prepare_enable(bank->dbck);
                bank->dbck_enabled = true;
 
                writel_relaxed(bank->dbck_enable_mask,
@@ -198,7 +196,7 @@ static inline void _gpio_dbck_disable(struct gpio_bank *bank)
                 */
                writel_relaxed(0, bank->base + bank->regs->debounce_en);
 
-               clk_disable(bank->dbck);
+               clk_disable_unprepare(bank->dbck);
                bank->dbck_enabled = false;
        }
 }
@@ -231,7 +229,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
 
        l = GPIO_BIT(bank, gpio);
 
-       clk_enable(bank->dbck);
+       clk_prepare_enable(bank->dbck);
        reg = bank->base + bank->regs->debounce;
        writel_relaxed(debounce, reg);
 
@@ -245,7 +243,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
        bank->dbck_enable_mask = val;
 
        writel_relaxed(val, reg);
-       clk_disable(bank->dbck);
+       clk_disable_unprepare(bank->dbck);
        /*
         * Enable debounce clock per module.
         * This call is mandatory because in omap_gpio_request() when
@@ -290,7 +288,7 @@ static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)
                bank->context.debounce = 0;
                writel_relaxed(bank->context.debounce, bank->base +
                             bank->regs->debounce);
-               clk_disable(bank->dbck);
+               clk_disable_unprepare(bank->dbck);
                bank->dbck_enabled = false;
        }
 }
@@ -299,7 +297,7 @@ static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
                                                unsigned trigger)
 {
        void __iomem *base = bank->base;
-       u32 gpio_bit = 1 << gpio;
+       u32 gpio_bit = BIT(gpio);
 
        _gpio_rmw(base, bank->regs->leveldetect0, gpio_bit,
                  trigger & IRQ_TYPE_LEVEL_LOW);
@@ -368,9 +366,9 @@ static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
 
        l = readl_relaxed(reg);
        if ((l >> gpio) & 1)
-               l &= ~(1 << gpio);
+               l &= ~(BIT(gpio));
        else
-               l |= 1 << gpio;
+               l |= BIT(gpio);
 
        writel_relaxed(l, reg);
 }
@@ -392,11 +390,11 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,
 
                l = readl_relaxed(reg);
                if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
-                       bank->toggle_mask |= 1 << gpio;
+                       bank->toggle_mask |= BIT(gpio);
                if (trigger & IRQ_TYPE_EDGE_RISING)
-                       l |= 1 << gpio;
+                       l |= BIT(gpio);
                else if (trigger & IRQ_TYPE_EDGE_FALLING)
-                       l &= ~(1 << gpio);
+                       l &= ~(BIT(gpio));
                else
                        return -EINVAL;
 
@@ -413,10 +411,10 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,
                if (trigger & IRQ_TYPE_EDGE_RISING)
                        l |= 2 << (gpio << 1);
                if (trigger & IRQ_TYPE_EDGE_FALLING)
-                       l |= 1 << (gpio << 1);
+                       l |= BIT(gpio << 1);
 
                /* Enable wake-up during idle for dynamic tick */
-               _gpio_rmw(base, bank->regs->wkup_en, 1 << gpio, trigger);
+               _gpio_rmw(base, bank->regs->wkup_en, BIT(gpio), trigger);
                bank->context.wake_en =
                        readl_relaxed(bank->base + bank->regs->wkup_en);
                writel_relaxed(l, reg);
@@ -430,7 +428,7 @@ static void _enable_gpio_module(struct gpio_bank *bank, unsigned offset)
                void __iomem *reg = bank->base + bank->regs->pinctrl;
 
                /* Claim the pin for MPU */
-               writel_relaxed(readl_relaxed(reg) | (1 << offset), reg);
+               writel_relaxed(readl_relaxed(reg) | (BIT(offset)), reg);
        }
 
        if (bank->regs->ctrl && !BANK_USED(bank)) {
@@ -453,7 +451,7 @@ static void _disable_gpio_module(struct gpio_bank *bank, unsigned offset)
            !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);
+               _gpio_rmw(base, bank->regs->wkup_en, BIT(offset), 0);
                bank->context.wake_en =
                        readl_relaxed(bank->base + bank->regs->wkup_en);
        }
@@ -479,7 +477,7 @@ static int gpio_is_input(struct gpio_bank *bank, int mask)
 
 static int gpio_irq_type(struct irq_data *d, unsigned type)
 {
-       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       struct gpio_bank *bank = _irq_data_get_bank(d);
        unsigned gpio = 0;
        int retval;
        unsigned long flags;
@@ -509,20 +507,12 @@ static int gpio_irq_type(struct irq_data *d, unsigned 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)) {
+       } else if (!gpio_is_input(bank, BIT(offset))) {
                spin_unlock_irqrestore(&bank->lock, flags);
                return -EINVAL;
        }
 
-       retval = gpio_lock_as_irq(&bank->chip, offset);
-       if (retval) {
-               dev_err(bank->dev, "unable to lock offset %d for IRQ\n",
-                       offset);
-               spin_unlock_irqrestore(&bank->lock, flags);
-               return retval;
-       }
-
-       bank->irq_usage |= 1 << GPIO_INDEX(bank, gpio);
+       bank->irq_usage |= BIT(GPIO_INDEX(bank, gpio));
        spin_unlock_irqrestore(&bank->lock, flags);
 
        if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
@@ -559,7 +549,7 @@ static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
 {
        void __iomem *reg = bank->base;
        u32 l;
-       u32 mask = (1 << bank->width) - 1;
+       u32 mask = (BIT(bank->width)) - 1;
 
        reg += bank->regs->irqenable;
        l = readl_relaxed(reg);
@@ -664,7 +654,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)
 /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
 static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
 {
-       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       struct gpio_bank *bank = _irq_data_get_bank(d);
        unsigned int gpio = irq_to_gpio(bank, d->hwirq);
 
        return _set_gpio_wakeup(bank, gpio, enable);
@@ -691,7 +681,7 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
                _set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
                _enable_gpio_module(bank, offset);
        }
-       bank->mod_usage |= 1 << offset;
+       bank->mod_usage |= BIT(offset);
        spin_unlock_irqrestore(&bank->lock, flags);
 
        return 0;
@@ -703,7 +693,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
        unsigned long flags;
 
        spin_lock_irqsave(&bank->lock, flags);
-       bank->mod_usage &= ~(1 << offset);
+       bank->mod_usage &= ~(BIT(offset));
        _disable_gpio_module(bank, offset);
        _reset_gpio(bank, bank->chip.base + offset);
        spin_unlock_irqrestore(&bank->lock, flags);
@@ -732,11 +722,12 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
        unsigned int bit;
        struct gpio_bank *bank;
        int unmasked = 0;
-       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct irq_chip *irqchip = irq_desc_get_chip(desc);
+       struct gpio_chip *chip = irq_get_handler_data(irq);
 
-       chained_irq_enter(chip, desc);
+       chained_irq_enter(irqchip, desc);
 
-       bank = irq_get_handler_data(irq);
+       bank = container_of(chip, struct gpio_bank, chip);
        isr_reg = bank->base + bank->regs->irqstatus;
        pm_runtime_get_sync(bank->dev);
 
@@ -764,7 +755,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                configured, we could unmask GPIO bank interrupt immediately */
                if (!level_mask && !unmasked) {
                        unmasked = 1;
-                       chained_irq_exit(chip, desc);
+                       chained_irq_exit(irqchip, desc);
                }
 
                if (!isr)
@@ -772,7 +763,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 
                while (isr) {
                        bit = __ffs(isr);
-                       isr &= ~(1 << bit);
+                       isr &= ~(BIT(bit));
 
                        /*
                         * Some chips can't respond to both rising and falling
@@ -781,10 +772,11 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                         * to respond to the IRQ for the opposite direction.
                         * This will be indicated in the bank toggle_mask.
                         */
-                       if (bank->toggle_mask & (1 << bit))
+                       if (bank->toggle_mask & (BIT(bit)))
                                _toggle_gpio_edge_triggering(bank, bit);
 
-                       generic_handle_irq(irq_find_mapping(bank->domain, bit));
+                       generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,
+                                                           bit));
                }
        }
        /* if bank has any level sensitive GPIO pin interrupt
@@ -793,20 +785,20 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
        interrupt */
 exit:
        if (!unmasked)
-               chained_irq_exit(chip, desc);
+               chained_irq_exit(irqchip, desc);
        pm_runtime_put(bank->dev);
 }
 
 static void gpio_irq_shutdown(struct irq_data *d)
 {
-       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       struct gpio_bank *bank = _irq_data_get_bank(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);
        gpio_unlock_as_irq(&bank->chip, offset);
-       bank->irq_usage &= ~(1 << offset);
+       bank->irq_usage &= ~(BIT(offset));
        _disable_gpio_module(bank, offset);
        _reset_gpio(bank, gpio);
        spin_unlock_irqrestore(&bank->lock, flags);
@@ -821,7 +813,7 @@ static void gpio_irq_shutdown(struct irq_data *d)
 
 static void gpio_ack_irq(struct irq_data *d)
 {
-       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       struct gpio_bank *bank = _irq_data_get_bank(d);
        unsigned int gpio = irq_to_gpio(bank, d->hwirq);
 
        _clear_gpio_irqstatus(bank, gpio);
@@ -829,7 +821,7 @@ static void gpio_ack_irq(struct irq_data *d)
 
 static void gpio_mask_irq(struct irq_data *d)
 {
-       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       struct gpio_bank *bank = _irq_data_get_bank(d);
        unsigned int gpio = irq_to_gpio(bank, d->hwirq);
        unsigned long flags;
 
@@ -841,7 +833,7 @@ static void gpio_mask_irq(struct irq_data *d)
 
 static void gpio_unmask_irq(struct irq_data *d)
 {
-       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       struct gpio_bank *bank = _irq_data_get_bank(d);
        unsigned int gpio = irq_to_gpio(bank, d->hwirq);
        unsigned int irq_mask = GPIO_BIT(bank, gpio);
        u32 trigger = irqd_get_trigger_type(d);
@@ -936,6 +928,21 @@ static inline void mpuio_init(struct gpio_bank *bank)
 
 /*---------------------------------------------------------------------*/
 
+static int gpio_get_direction(struct gpio_chip *chip, unsigned offset)
+{
+       struct gpio_bank *bank;
+       unsigned long flags;
+       void __iomem *reg;
+       int dir;
+
+       bank = container_of(chip, struct gpio_bank, chip);
+       reg = bank->base + bank->regs->direction;
+       spin_lock_irqsave(&bank->lock, flags);
+       dir = !!(readl_relaxed(reg) & BIT(offset));
+       spin_unlock_irqrestore(&bank->lock, flags);
+       return dir;
+}
+
 static int gpio_input(struct gpio_chip *chip, unsigned offset)
 {
        struct gpio_bank *bank;
@@ -954,7 +961,7 @@ static int gpio_get(struct gpio_chip *chip, unsigned offset)
        u32 mask;
 
        bank = container_of(chip, struct gpio_bank, chip);
-       mask = (1 << offset);
+       mask = (BIT(offset));
 
        if (gpio_is_input(bank, mask))
                return _get_gpio_datain(bank, offset);
@@ -1081,10 +1088,12 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
                               IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 }
 
-static void omap_gpio_chip_init(struct gpio_bank *bank)
+static int omap_gpio_chip_init(struct gpio_bank *bank)
 {
        int j;
        static int gpio;
+       int irq_base = 0;
+       int ret;
 
        /*
         * REVISIT eventually switch from OMAP-specific gpio structs
@@ -1092,12 +1101,12 @@ static void omap_gpio_chip_init(struct gpio_bank *bank)
         */
        bank->chip.request = omap_gpio_request;
        bank->chip.free = omap_gpio_free;
+       bank->chip.get_direction = gpio_get_direction;
        bank->chip.direction_input = gpio_input;
        bank->chip.get = gpio_get;
        bank->chip.direction_output = gpio_output;
        bank->chip.set_debounce = gpio_debounce;
        bank->chip.set = gpio_set;
-       bank->chip.to_irq = omap_gpio_to_irq;
        if (bank->is_mpuio) {
                bank->chip.label = "mpuio";
                if (bank->regs->wkup_en)
@@ -1110,22 +1119,48 @@ static void omap_gpio_chip_init(struct gpio_bank *bank)
        }
        bank->chip.ngpio = bank->width;
 
-       gpiochip_add(&bank->chip);
+       ret = gpiochip_add(&bank->chip);
+       if (ret) {
+               dev_err(bank->dev, "Could not register gpio chip %d\n", ret);
+               return ret;
+       }
+
+#ifdef CONFIG_ARCH_OMAP1
+       /*
+        * REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop
+        * irq_alloc_descs() since a base IRQ offset will no longer be needed.
+        */
+       irq_base = irq_alloc_descs(-1, 0, bank->width, 0);
+       if (irq_base < 0) {
+               dev_err(bank->dev, "Couldn't allocate IRQ numbers\n");
+               return -ENODEV;
+       }
+#endif
+
+       ret = gpiochip_irqchip_add(&bank->chip, &gpio_irq_chip,
+                                  irq_base, gpio_irq_handler,
+                                  IRQ_TYPE_NONE);
+
+       if (ret) {
+               dev_err(bank->dev, "Couldn't add irqchip to gpiochip %d\n", ret);
+               ret = gpiochip_remove(&bank->chip);
+               return -ENODEV;
+       }
+
+       gpiochip_set_chained_irqchip(&bank->chip, &gpio_irq_chip,
+                                    bank->irq, gpio_irq_handler);
 
        for (j = 0; j < bank->width; j++) {
-               int irq = irq_create_mapping(bank->domain, j);
+               int irq = irq_find_mapping(bank->chip.irqdomain, j);
                irq_set_lockdep_class(irq, &gpio_lock_class);
-               irq_set_chip_data(irq, bank);
                if (bank->is_mpuio) {
                        omap_mpuio_alloc_gc(bank, irq, bank->width);
-               } else {
-                       irq_set_chip_and_handler(irq, &gpio_irq_chip,
-                                                handle_simple_irq);
-                       set_irq_flags(irq, IRQF_VALID);
+                       irq_set_chip_and_handler(irq, NULL, NULL);
+                       set_irq_flags(irq, 0);
                }
        }
-       irq_set_chained_handler(bank->irq, gpio_irq_handler);
-       irq_set_handler_data(bank->irq, bank);
+
+       return 0;
 }
 
 static const struct of_device_id omap_gpio_match[];
@@ -1138,9 +1173,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
        const struct omap_gpio_platform_data *pdata;
        struct resource *res;
        struct gpio_bank *bank;
-#ifdef CONFIG_ARCH_OMAP1
-       int irq_base;
-#endif
+       int ret;
 
        match = of_match_device(of_match_ptr(omap_gpio_match), dev);
 
@@ -1162,6 +1195,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
 
        bank->irq = res->start;
        bank->dev = dev;
+       bank->chip.dev = dev;
        bank->dbck_flag = pdata->dbck_flag;
        bank->stride = pdata->bank_stride;
        bank->width = pdata->bank_width;
@@ -1182,29 +1216,6 @@ static int omap_gpio_probe(struct platform_device *pdev)
                                pdata->get_context_loss_count;
        }
 
-#ifdef CONFIG_ARCH_OMAP1
-       /*
-        * REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop
-        * irq_alloc_descs() and irq_domain_add_legacy() and just use a
-        * linear IRQ domain mapping for all OMAP platforms.
-        */
-       irq_base = irq_alloc_descs(-1, 0, bank->width, 0);
-       if (irq_base < 0) {
-               dev_err(dev, "Couldn't allocate IRQ numbers\n");
-               return -ENODEV;
-       }
-
-       bank->domain = irq_domain_add_legacy(node, bank->width, irq_base,
-                                            0, &irq_domain_simple_ops, NULL);
-#else
-       bank->domain = irq_domain_add_linear(node, bank->width,
-                                            &irq_domain_simple_ops, NULL);
-#endif
-       if (!bank->domain) {
-               dev_err(dev, "Couldn't register an IRQ domain\n");
-               return -ENODEV;
-       }
-
        if (bank->regs->set_dataout && bank->regs->clr_dataout)
                bank->set_dataout = _set_gpio_dataout_reg;
        else
@@ -1216,7 +1227,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        bank->base = devm_ioremap_resource(dev, res);
        if (IS_ERR(bank->base)) {
-               irq_domain_remove(bank->domain);
+               irq_domain_remove(bank->chip.irqdomain);
                return PTR_ERR(bank->base);
        }
 
@@ -1230,7 +1241,11 @@ static int omap_gpio_probe(struct platform_device *pdev)
                mpuio_init(bank);
 
        omap_gpio_mod_init(bank);
-       omap_gpio_chip_init(bank);
+
+       ret = omap_gpio_chip_init(bank);
+       if (ret)
+               return ret;
+
        omap_gpio_show_rev(bank);
 
        pm_runtime_put(bank->dev);
index da9d33252e5603fcc8712db61bb684198fda4673..86bdbe362068db02b61b2a2bbbdfd3f1cdf0aa2b 100644 (file)
@@ -148,7 +148,7 @@ static const struct palmas_device_data tps80036_dev_data = {
        .ngpio = 16,
 };
 
-static struct of_device_id of_palmas_gpio_match[] = {
+static const struct of_device_id of_palmas_gpio_match[] = {
        { .compatible = "ti,palmas-gpio", .data = &palmas_dev_data,},
        { .compatible = "ti,tps65913-gpio", .data = &palmas_dev_data,},
        { .compatible = "ti,tps65914-gpio", .data = &palmas_dev_data,},
@@ -173,10 +173,8 @@ static int palmas_gpio_probe(struct platform_device *pdev)
 
        palmas_gpio = devm_kzalloc(&pdev->dev,
                                sizeof(*palmas_gpio), GFP_KERNEL);
-       if (!palmas_gpio) {
-               dev_err(&pdev->dev, "Could not allocate palmas_gpio\n");
+       if (!palmas_gpio)
                return -ENOMEM;
-       }
 
        palmas_gpio->palmas = palmas;
        palmas_gpio->gpio_chip.owner = THIS_MODULE;
index d550d8e58705524b78753289b372abd7ae39818c..e721a37c3473efb5168dcb8c664fe1abe0c2a6d7 100644 (file)
@@ -15,8 +15,6 @@
 #include <linux/init.h>
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
 #include <linux/i2c.h>
 #include <linux/platform_data/pca953x.h>
 #include <linux/slab.h>
@@ -91,7 +89,6 @@ struct pca953x_chip {
        u8 irq_stat[MAX_BANK];
        u8 irq_trig_raise[MAX_BANK];
        u8 irq_trig_fall[MAX_BANK];
-       struct irq_domain *domain;
 #endif
 
        struct i2c_client *client;
@@ -100,6 +97,11 @@ struct pca953x_chip {
        int     chip_type;
 };
 
+static inline struct pca953x_chip *to_pca(struct gpio_chip *gc)
+{
+       return container_of(gc, struct pca953x_chip, gpio_chip);
+}
+
 static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val,
                                int off)
 {
@@ -202,12 +204,10 @@ static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val)
 
 static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
 {
-       struct pca953x_chip *chip;
+       struct pca953x_chip *chip = to_pca(gc);
        u8 reg_val;
        int ret, offset = 0;
 
-       chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
        mutex_lock(&chip->i2c_lock);
        reg_val = chip->reg_direction[off / BANK_SZ] | (1u << (off % BANK_SZ));
 
@@ -233,12 +233,10 @@ exit:
 static int pca953x_gpio_direction_output(struct gpio_chip *gc,
                unsigned off, int val)
 {
-       struct pca953x_chip *chip;
+       struct pca953x_chip *chip = to_pca(gc);
        u8 reg_val;
        int ret, offset = 0;
 
-       chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
        mutex_lock(&chip->i2c_lock);
        /* set output level */
        if (val)
@@ -285,12 +283,10 @@ exit:
 
 static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
 {
-       struct pca953x_chip *chip;
+       struct pca953x_chip *chip = to_pca(gc);
        u32 reg_val;
        int ret, offset = 0;
 
-       chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
        mutex_lock(&chip->i2c_lock);
        switch (chip->chip_type) {
        case PCA953X_TYPE:
@@ -315,12 +311,10 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
 
 static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
 {
-       struct pca953x_chip *chip;
+       struct pca953x_chip *chip = to_pca(gc);
        u8 reg_val;
        int ret, offset = 0;
 
-       chip = container_of(gc, struct pca953x_chip, gpio_chip);
-
        mutex_lock(&chip->i2c_lock);
        if (val)
                reg_val = chip->reg_output[off / BANK_SZ]
@@ -367,38 +361,34 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
 }
 
 #ifdef CONFIG_GPIO_PCA953X_IRQ
-static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
-{
-       struct pca953x_chip *chip;
-
-       chip = container_of(gc, struct pca953x_chip, gpio_chip);
-       return irq_create_mapping(chip->domain, off);
-}
-
 static void pca953x_irq_mask(struct irq_data *d)
 {
-       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct pca953x_chip *chip = to_pca(gc);
 
        chip->irq_mask[d->hwirq / BANK_SZ] &= ~(1 << (d->hwirq % BANK_SZ));
 }
 
 static void pca953x_irq_unmask(struct irq_data *d)
 {
-       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct pca953x_chip *chip = to_pca(gc);
 
        chip->irq_mask[d->hwirq / BANK_SZ] |= 1 << (d->hwirq % BANK_SZ);
 }
 
 static void pca953x_irq_bus_lock(struct irq_data *d)
 {
-       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct pca953x_chip *chip = to_pca(gc);
 
        mutex_lock(&chip->irq_lock);
 }
 
 static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
 {
-       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct pca953x_chip *chip = to_pca(gc);
        u8 new_irqs;
        int level, i;
 
@@ -420,7 +410,8 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
 
 static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
 {
-       struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct pca953x_chip *chip = to_pca(gc);
        int bank_nb = d->hwirq / BANK_SZ;
        u8 mask = 1 << (d->hwirq % BANK_SZ);
 
@@ -503,44 +494,25 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
        struct pca953x_chip *chip = devid;
        u8 pending[MAX_BANK];
        u8 level;
+       unsigned nhandled = 0;
        int i;
 
        if (!pca953x_irq_pending(chip, pending))
-               return IRQ_HANDLED;
+               return IRQ_NONE;
 
        for (i = 0; i < NBANK(chip); i++) {
                while (pending[i]) {
                        level = __ffs(pending[i]);
-                       handle_nested_irq(irq_find_mapping(chip->domain,
+                       handle_nested_irq(irq_find_mapping(chip->gpio_chip.irqdomain,
                                                        level + (BANK_SZ * i)));
                        pending[i] &= ~(1 << level);
+                       nhandled++;
                }
        }
 
-       return IRQ_HANDLED;
+       return (nhandled > 0) ? IRQ_HANDLED : IRQ_NONE;
 }
 
-static int pca953x_gpio_irq_map(struct irq_domain *d, unsigned int irq,
-                      irq_hw_number_t hwirq)
-{
-       irq_clear_status_flags(irq, IRQ_NOREQUEST);
-       irq_set_chip_data(irq, d->host_data);
-       irq_set_chip(irq, &pca953x_irq_chip);
-       irq_set_nested_thread(irq, true);
-#ifdef CONFIG_ARM
-       set_irq_flags(irq, IRQF_VALID);
-#else
-       irq_set_noprobe(irq);
-#endif
-
-       return 0;
-}
-
-static const struct irq_domain_ops pca953x_irq_simple_ops = {
-       .map = pca953x_gpio_irq_map,
-       .xlate = irq_domain_xlate_twocell,
-};
-
 static int pca953x_irq_setup(struct pca953x_chip *chip,
                             const struct i2c_device_id *id,
                             int irq_base)
@@ -572,19 +544,12 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
                        chip->irq_stat[i] &= chip->reg_direction[i];
                mutex_init(&chip->irq_lock);
 
-               chip->domain = irq_domain_add_simple(client->dev.of_node,
-                                               chip->gpio_chip.ngpio,
-                                               irq_base,
-                                               &pca953x_irq_simple_ops,
-                                               chip);
-               if (!chip->domain)
-                       return -ENODEV;
-
                ret = devm_request_threaded_irq(&client->dev,
                                        client->irq,
                                           NULL,
                                           pca953x_irq_handler,
-                                          IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+                                          IRQF_TRIGGER_LOW | IRQF_ONESHOT |
+                                                  IRQF_SHARED,
                                           dev_name(&client->dev), chip);
                if (ret) {
                        dev_err(&client->dev, "failed to request irq %d\n",
@@ -592,7 +557,16 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
                        return ret;
                }
 
-               chip->gpio_chip.to_irq = pca953x_gpio_to_irq;
+               ret =  gpiochip_irqchip_add(&chip->gpio_chip,
+                                           &pca953x_irq_chip,
+                                           irq_base,
+                                           handle_simple_irq,
+                                           IRQ_TYPE_NONE);
+               if (ret) {
+                       dev_err(&client->dev,
+                               "could not connect irqchip to gpiochip\n");
+                       return ret;
+               }
        }
 
        return 0;
@@ -756,11 +730,11 @@ static int pca953x_probe(struct i2c_client *client,
        if (ret)
                return ret;
 
-       ret = pca953x_irq_setup(chip, id, irq_base);
+       ret = gpiochip_add(&chip->gpio_chip);
        if (ret)
                return ret;
 
-       ret = gpiochip_add(&chip->gpio_chip);
+       ret = pca953x_irq_setup(chip, id, irq_base);
        if (ret)
                return ret;
 
index 82735822bc9d633ae8e54dc2df3e3b5e3ebd5b73..27b46751ea7e86756f80e1c28664fe5736ca351b 100644 (file)
@@ -262,7 +262,7 @@ static int pcf857x_irq_domain_init(struct pcf857x *gpio,
        /* enable real irq */
        status = devm_request_threaded_irq(&client->dev, client->irq,
                                NULL, pcf857x_irq, IRQF_ONESHOT |
-                               IRQF_TRIGGER_FALLING,
+                               IRQF_TRIGGER_FALLING | IRQF_SHARED,
                                dev_name(&client->dev), gpio);
 
        if (status)
@@ -319,7 +319,7 @@ static int pcf857x_probe(struct i2c_client *client,
                status = pcf857x_irq_domain_init(gpio, client);
                if (status < 0) {
                        dev_err(&client->dev, "irq_domain init failed\n");
-                       goto fail;
+                       goto fail_irq_domain;
                }
        }
 
@@ -414,12 +414,13 @@ static int pcf857x_probe(struct i2c_client *client,
        return 0;
 
 fail:
-       dev_dbg(&client->dev, "probe error %d for '%s'\n",
-                       status, client->name);
-
        if (client->irq)
                pcf857x_irq_domain_cleanup(gpio);
 
+fail_irq_domain:
+       dev_dbg(&client->dev, "probe error %d for '%s'\n",
+               status, client->name);
+
        return status;
 }
 
index 83a15639747415e0d27cdc6979ce60950f2e484d..d6eac9b17db9ef33803a68f98097347d5543097b 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/slab.h>
 
 #define PCH_EDGE_FALLING       0
 #define PCH_EDGE_RISING                BIT(0)
index b0f475243cef6851a41028ce411f806fe70ef3d3..84b49cfb81a8b3a12f0c8c3ab2e52c6cb83bf924 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/irq.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/bitops.h>
-#include <linux/workqueue.h>
 #include <linux/gpio.h>
 #include <linux/device.h>
 #include <linux/amba/bus.h>
@@ -88,7 +87,7 @@ static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
 
        spin_lock_irqsave(&chip->lock, flags);
        gpiodir = readb(chip->base + GPIODIR);
-       gpiodir &= ~(1 << offset);
+       gpiodir &= ~(BIT(offset));
        writeb(gpiodir, chip->base + GPIODIR);
        spin_unlock_irqrestore(&chip->lock, flags);
 
@@ -106,16 +105,16 @@ static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
                return -EINVAL;
 
        spin_lock_irqsave(&chip->lock, flags);
-       writeb(!!value << offset, chip->base + (1 << (offset + 2)));
+       writeb(!!value << offset, chip->base + (BIT(offset + 2)));
        gpiodir = readb(chip->base + GPIODIR);
-       gpiodir |= 1 << offset;
+       gpiodir |= BIT(offset);
        writeb(gpiodir, chip->base + GPIODIR);
 
        /*
         * gpio value is set again, because pl061 doesn't allow to set value of
         * a gpio pin before configuring it in OUT mode.
         */
-       writeb(!!value << offset, chip->base + (1 << (offset + 2)));
+       writeb(!!value << offset, chip->base + (BIT(offset + 2)));
        spin_unlock_irqrestore(&chip->lock, flags);
 
        return 0;
@@ -125,14 +124,14 @@ static int pl061_get_value(struct gpio_chip *gc, unsigned offset)
 {
        struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
 
-       return !!readb(chip->base + (1 << (offset + 2)));
+       return !!readb(chip->base + (BIT(offset + 2)));
 }
 
 static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)
 {
        struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
 
-       writeb(!!value << offset, chip->base + (1 << (offset + 2)));
+       writeb(!!value << offset, chip->base + (BIT(offset + 2)));
 }
 
 static int pl061_irq_type(struct irq_data *d, unsigned trigger)
@@ -207,7 +206,7 @@ static void pl061_irq_mask(struct irq_data *d)
 {
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
-       u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR);
+       u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
        u8 gpioie;
 
        spin_lock(&chip->lock);
@@ -220,7 +219,7 @@ static void pl061_irq_unmask(struct irq_data *d)
 {
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
-       u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR);
+       u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
        u8 gpioie;
 
        spin_lock(&chip->lock);
@@ -302,9 +301,9 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
 
        for (i = 0; i < PL061_GPIO_NR; i++) {
                if (pdata) {
-                       if (pdata->directions & (1 << i))
+                       if (pdata->directions & (BIT(i)))
                                pl061_direction_output(&chip->gc, i,
-                                               pdata->values & (1 << i));
+                                               pdata->values & (BIT(i)));
                        else
                                pl061_direction_input(&chip->gc, i);
                }
@@ -331,7 +330,7 @@ static int pl061_suspend(struct device *dev)
        chip->csave_regs.gpio_ie = readb(chip->base + GPIOIE);
 
        for (offset = 0; offset < PL061_GPIO_NR; offset++) {
-               if (chip->csave_regs.gpio_dir & (1 << offset))
+               if (chip->csave_regs.gpio_dir & (BIT(offset)))
                        chip->csave_regs.gpio_data |=
                                pl061_get_value(&chip->gc, offset) << offset;
        }
@@ -345,10 +344,10 @@ static int pl061_resume(struct device *dev)
        int offset;
 
        for (offset = 0; offset < PL061_GPIO_NR; offset++) {
-               if (chip->csave_regs.gpio_dir & (1 << offset))
+               if (chip->csave_regs.gpio_dir & (BIT(offset)))
                        pl061_direction_output(&chip->gc, offset,
                                        chip->csave_regs.gpio_data &
-                                       (1 << offset));
+                                       (BIT(offset)));
                else
                        pl061_direction_input(&chip->gc, offset);
        }
index 9b423173ab50a949e152645511f8badc40421d41..562b0c4d9cc888a01af998e48c337ace1a23ce4e 100644 (file)
@@ -119,10 +119,8 @@ static int rc5t583_gpio_probe(struct platform_device *pdev)
 
        rc5t583_gpio = devm_kzalloc(&pdev->dev, sizeof(*rc5t583_gpio),
                                        GFP_KERNEL);
-       if (!rc5t583_gpio) {
-               dev_warn(&pdev->dev, "Mem allocation for rc5t583_gpio failed");
+       if (!rc5t583_gpio)
                return -ENOMEM;
-       }
 
        rc5t583_gpio->gpio_chip.label = "gpio-rc5t583",
        rc5t583_gpio->gpio_chip.owner = THIS_MODULE,
index 03c91482432cfb62f9feae0279d3905eaec90f6b..0c9f803fc1acdb3fe9e6798ce506e1ec21a41680 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_data/gpio-rcar.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 
@@ -362,7 +363,6 @@ static int gpio_rcar_probe(struct platform_device *pdev)
 
        p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);
        if (!p) {
-               dev_err(dev, "failed to allocate driver data\n");
                ret = -ENOMEM;
                goto err0;
        }
@@ -377,6 +377,9 @@ static int gpio_rcar_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, p);
 
+       pm_runtime_enable(dev);
+       pm_runtime_get_sync(dev);
+
        io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 
@@ -460,6 +463,8 @@ static int gpio_rcar_probe(struct platform_device *pdev)
 err1:
        irq_domain_remove(p->irq_domain);
 err0:
+       pm_runtime_put(dev);
+       pm_runtime_disable(dev);
        return ret;
 }
 
@@ -473,6 +478,8 @@ static int gpio_rcar_remove(struct platform_device *pdev)
                return ret;
 
        irq_domain_remove(p->irq_domain);
+       pm_runtime_put(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
        return 0;
 }
 
index 88577c3272a5536871f903e199aaf2a7bd37d3eb..9fa7e53331c92b8a04eb175b647ed9b2a69e1eda 100644 (file)
@@ -141,17 +141,15 @@ static int rdc321x_gpio_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       rdc321x_gpio_dev = kzalloc(sizeof(struct rdc321x_gpio), GFP_KERNEL);
-       if (!rdc321x_gpio_dev) {
-               dev_err(&pdev->dev, "failed to allocate private data\n");
+       rdc321x_gpio_dev = devm_kzalloc(&pdev->dev, sizeof(struct rdc321x_gpio),
+                                       GFP_KERNEL);
+       if (!rdc321x_gpio_dev)
                return -ENOMEM;
-       }
 
        r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg1");
        if (!r) {
                dev_err(&pdev->dev, "failed to get gpio-reg1 resource\n");
-               err = -ENODEV;
-               goto out_free;
+               return -ENODEV;
        }
 
        spin_lock_init(&rdc321x_gpio_dev->lock);
@@ -162,8 +160,7 @@ static int rdc321x_gpio_probe(struct platform_device *pdev)
        r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg2");
        if (!r) {
                dev_err(&pdev->dev, "failed to get gpio-reg2 resource\n");
-               err = -ENODEV;
-               goto out_free;
+               return -ENODEV;
        }
 
        rdc321x_gpio_dev->reg2_ctrl_base = r->start;
@@ -187,21 +184,17 @@ static int rdc321x_gpio_probe(struct platform_device *pdev)
                                        rdc321x_gpio_dev->reg1_data_base,
                                        &rdc321x_gpio_dev->data_reg[0]);
        if (err)
-               goto out_free;
+               return err;
 
        err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
                                        rdc321x_gpio_dev->reg2_data_base,
                                        &rdc321x_gpio_dev->data_reg[1]);
        if (err)
-               goto out_free;
+               return err;
 
        dev_info(&pdev->dev, "registering %d GPIOs\n",
                                        rdc321x_gpio_dev->chip.ngpio);
        return gpiochip_add(&rdc321x_gpio_dev->chip);
-
-out_free:
-       kfree(rdc321x_gpio_dev);
-       return err;
 }
 
 static int rdc321x_gpio_remove(struct platform_device *pdev)
@@ -213,8 +206,6 @@ static int rdc321x_gpio_remove(struct platform_device *pdev)
        if (ret)
                dev_err(&pdev->dev, "failed to unregister chip\n");
 
-       kfree(rdc321x_gpio_dev);
-
        return ret;
 }
 
index 5af65719b95dafad605fb8f1f733ead623b78bf5..a9b1cd16c848317e887523363516bb465788180c 100644 (file)
@@ -97,8 +97,6 @@ static int sch_gpio_core_direction_out(struct gpio_chip *gc,
        u8 curr_dirs;
        unsigned short offset, bit;
 
-       sch_gpio_core_set(gc, gpio_num, val);
-
        spin_lock(&gpio_lock);
 
        offset = CGIO + gpio_num / 8;
@@ -109,6 +107,17 @@ static int sch_gpio_core_direction_out(struct gpio_chip *gc,
                outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
 
        spin_unlock(&gpio_lock);
+
+       /*
+        * according to the datasheet, writing to the level register has no
+        * effect when GPIO is programmed as input.
+        * Actually the the level register is read-only when configured as input.
+        * Thus presetting the output level before switching to output is _NOT_ possible.
+        * Hence we set the level after configuring the GPIO as output.
+        * But we cannot prevent a short low pulse if direction is set to high
+        * and an external pull-up is connected.
+        */
+       sch_gpio_core_set(gc, gpio_num, val);
        return 0;
 }
 
@@ -178,8 +187,6 @@ static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
        u8 curr_dirs;
        unsigned short offset, bit;
 
-       sch_gpio_resume_set(gc, gpio_num, val);
-
        offset = RGIO + gpio_num / 8;
        bit = gpio_num % 8;
 
@@ -190,6 +197,17 @@ static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
                outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
 
        spin_unlock(&gpio_lock);
+
+       /*
+       * according to the datasheet, writing to the level register has no
+       * effect when GPIO is programmed as input.
+       * Actually the the level register is read-only when configured as input.
+       * Thus presetting the output level before switching to output is _NOT_ possible.
+       * Hence we set the level after configuring the GPIO as output.
+       * But we cannot prevent a short low pulse if direction is set to high
+       * and an external pull-up is connected.
+       */
+       sch_gpio_resume_set(gc, gpio_num, val);
        return 0;
 }
 
index 0357387b3645321de91c338b826f02e4120d211b..f942b80ee403fb1499dfa21323a2c1edd7e12e81 100644 (file)
@@ -327,14 +327,22 @@ static int __init sch311x_detect(int sio_config_port, unsigned short *addr)
        if (err)
                return err;
 
-       /* Check device ID. We currently know about:
-        * SCH3112 (0x7c), SCH3114 (0x7d), and SCH3116 (0x7f). */
+       /* Check device ID. */
        reg = sch311x_sio_inb(sio_config_port, 0x20);
-       if (!(reg == 0x7c || reg == 0x7d || reg == 0x7f)) {
+       switch (reg) {
+       case 0x7c: /* SCH3112 */
+               dev_id = 2;
+               break;
+       case 0x7d: /* SCH3114 */
+               dev_id = 4;
+               break;
+       case 0x7f: /* SCH3116 */
+               dev_id = 6;
+               break;
+       default:
                err = -ENODEV;
                goto exit;
        }
-       dev_id = reg == 0x7c ? 2 : reg == 0x7d ? 4 : 6;
 
        /* Select logical device A (runtime registers) */
        sch311x_sio_outb(sio_config_port, 0x07, 0x0a);
index 30bcc539425d10cd4a7dfcd29720f0e8f98017c7..353263c85d26f9ebdcad341ad42fd081751f8598 100644 (file)
@@ -129,10 +129,8 @@ static int spics_gpio_probe(struct platform_device *pdev)
        int ret;
 
        spics = devm_kzalloc(&pdev->dev, sizeof(*spics), GFP_KERNEL);
-       if (!spics) {
-               dev_err(&pdev->dev, "memory allocation fail\n");
+       if (!spics)
                return -ENOMEM;
-       }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        spics->base = devm_ioremap_resource(&pdev->dev, res);
index 13d73fb2b5e1a2b0346b3cd8e75c4436795cca39..b51ca9f5c14018e3213aed4ccdf38c7a3d52a8f1 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
-#include <linux/workqueue.h>
 #include <linux/i2c/sx150x.h>
 
 #define NO_UPDATE_PENDING      -1
index 1019320984d778f8fd51a26d3be93551349feef8..51f7cbd9ff713cc9d3c52a9f7e4565f5ceb68554 100644 (file)
@@ -12,8 +12,6 @@
 #include <linux/slab.h>
 #include <linux/gpio.h>
 #include <linux/of.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
 #include <linux/interrupt.h>
 #include <linux/mfd/tc3589x.h>
 
@@ -31,10 +29,6 @@ struct tc3589x_gpio {
        struct tc3589x *tc3589x;
        struct device *dev;
        struct mutex irq_lock;
-       struct irq_domain *domain;
-
-       int irq_base;
-
        /* Caches of interrupt control registers for bus_lock */
        u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
        u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
@@ -95,30 +89,6 @@ static int tc3589x_gpio_direction_input(struct gpio_chip *chip,
        return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0);
 }
 
-/**
- * tc3589x_gpio_irq_get_irq(): Map a hardware IRQ on a chip to a Linux IRQ
- *
- * @tc3589x_gpio: tc3589x_gpio_irq controller to operate on.
- * @irq: index of the hardware interrupt requested in the chip IRQs
- *
- * Useful for drivers to request their own IRQs.
- */
-static int tc3589x_gpio_irq_get_irq(struct tc3589x_gpio *tc3589x_gpio,
-                                    int hwirq)
-{
-       if (!tc3589x_gpio)
-               return -EINVAL;
-
-       return irq_create_mapping(tc3589x_gpio->domain, hwirq);
-}
-
-static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
-
-       return tc3589x_gpio_irq_get_irq(tc3589x_gpio, offset);
-}
-
 static struct gpio_chip template_chip = {
        .label                  = "tc3589x",
        .owner                  = THIS_MODULE,
@@ -126,13 +96,13 @@ static struct gpio_chip template_chip = {
        .get                    = tc3589x_gpio_get,
        .direction_output       = tc3589x_gpio_direction_output,
        .set                    = tc3589x_gpio_set,
-       .to_irq                 = tc3589x_gpio_to_irq,
        .can_sleep              = true,
 };
 
 static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
-       struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
        int offset = d->hwirq;
        int regoffset = offset / 8;
        int mask = 1 << (offset % 8);
@@ -159,14 +129,16 @@ static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 
 static void tc3589x_gpio_irq_lock(struct irq_data *d)
 {
-       struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
 
        mutex_lock(&tc3589x_gpio->irq_lock);
 }
 
 static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
 {
-       struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
        struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
        static const u8 regmap[] = {
                [REG_IBE]       = TC3589x_GPIOIBE0,
@@ -194,7 +166,8 @@ static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
 
 static void tc3589x_gpio_irq_mask(struct irq_data *d)
 {
-       struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
        int offset = d->hwirq;
        int regoffset = offset / 8;
        int mask = 1 << (offset % 8);
@@ -204,7 +177,8 @@ static void tc3589x_gpio_irq_mask(struct irq_data *d)
 
 static void tc3589x_gpio_irq_unmask(struct irq_data *d)
 {
-       struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
        int offset = d->hwirq;
        int regoffset = offset / 8;
        int mask = 1 << (offset % 8);
@@ -242,7 +216,8 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
                while (stat) {
                        int bit = __ffs(stat);
                        int line = i * 8 + bit;
-                       int irq = tc3589x_gpio_irq_get_irq(tc3589x_gpio, line);
+                       int irq = irq_find_mapping(tc3589x_gpio->chip.irqdomain,
+                                                  line);
 
                        handle_nested_irq(irq);
                        stat &= ~(1 << bit);
@@ -254,61 +229,6 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
        return IRQ_HANDLED;
 }
 
-static int tc3589x_gpio_irq_map(struct irq_domain *d, unsigned int irq,
-                               irq_hw_number_t hwirq)
-{
-       struct tc3589x *tc3589x_gpio = d->host_data;
-
-       irq_set_chip_data(irq, tc3589x_gpio);
-       irq_set_chip_and_handler(irq, &tc3589x_gpio_irq_chip,
-                               handle_simple_irq);
-       irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-       set_irq_flags(irq, IRQF_VALID);
-#else
-       irq_set_noprobe(irq);
-#endif
-
-       return 0;
-}
-
-static void tc3589x_gpio_irq_unmap(struct irq_domain *d, unsigned int irq)
-{
-#ifdef CONFIG_ARM
-       set_irq_flags(irq, 0);
-#endif
-       irq_set_chip_and_handler(irq, NULL, NULL);
-       irq_set_chip_data(irq, NULL);
-}
-
-static struct irq_domain_ops tc3589x_irq_ops = {
-       .map    = tc3589x_gpio_irq_map,
-       .unmap  = tc3589x_gpio_irq_unmap,
-       .xlate  = irq_domain_xlate_twocell,
-};
-
-static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio,
-                               struct device_node *np)
-{
-       int base = tc3589x_gpio->irq_base;
-
-       /*
-        * If this results in a linear domain, irq_create_mapping() will
-        * take care of allocating IRQ descriptors at runtime. When a base
-        * is provided, the IRQ descriptors will be allocated when the
-        * domain is instantiated.
-        */
-       tc3589x_gpio->domain = irq_domain_add_simple(np,
-                       tc3589x_gpio->chip.ngpio, base, &tc3589x_irq_ops,
-                       tc3589x_gpio);
-       if (!tc3589x_gpio->domain) {
-               dev_err(tc3589x_gpio->dev, "Failed to create irqdomain\n");
-               return -ENOSYS;
-       }
-
-       return 0;
-}
-
 static int tc3589x_gpio_probe(struct platform_device *pdev)
 {
        struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
@@ -329,7 +249,8 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
        if (irq < 0)
                return irq;
 
-       tc3589x_gpio = kzalloc(sizeof(struct tc3589x_gpio), GFP_KERNEL);
+       tc3589x_gpio = devm_kzalloc(&pdev->dev, sizeof(struct tc3589x_gpio),
+                                   GFP_KERNEL);
        if (!tc3589x_gpio)
                return -ENOMEM;
 
@@ -347,30 +268,36 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
        tc3589x_gpio->chip.of_node = np;
 #endif
 
-       tc3589x_gpio->irq_base = tc3589x->irq_base ?
-               tc3589x->irq_base + TC3589x_INT_GPIO(0) : 0;
-
        /* Bring the GPIO module out of reset */
        ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL,
                               TC3589x_RSTCTRL_GPIRST, 0);
        if (ret < 0)
-               goto out_free;
-
-       ret = tc3589x_gpio_irq_init(tc3589x_gpio, np);
-       if (ret)
-               goto out_free;
+               return ret;
 
-       ret = request_threaded_irq(irq, NULL, tc3589x_gpio_irq, IRQF_ONESHOT,
-                                  "tc3589x-gpio", tc3589x_gpio);
+       ret = devm_request_threaded_irq(&pdev->dev,
+                                       irq, NULL, tc3589x_gpio_irq,
+                                       IRQF_ONESHOT, "tc3589x-gpio",
+                                       tc3589x_gpio);
        if (ret) {
                dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
-               goto out_free;
+               return ret;
        }
 
        ret = gpiochip_add(&tc3589x_gpio->chip);
        if (ret) {
                dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
-               goto out_freeirq;
+               return ret;
+       }
+
+       ret =  gpiochip_irqchip_add(&tc3589x_gpio->chip,
+                                   &tc3589x_gpio_irq_chip,
+                                   0,
+                                   handle_simple_irq,
+                                   IRQ_TYPE_NONE);
+       if (ret) {
+               dev_err(&pdev->dev,
+                       "could not connect irqchip to gpiochip\n");
+               return ret;
        }
 
        if (pdata && pdata->setup)
@@ -379,12 +306,6 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, tc3589x_gpio);
 
        return 0;
-
-out_freeirq:
-       free_irq(irq, tc3589x_gpio);
-out_free:
-       kfree(tc3589x_gpio);
-       return ret;
 }
 
 static int tc3589x_gpio_remove(struct platform_device *pdev)
@@ -392,7 +313,6 @@ static int tc3589x_gpio_remove(struct platform_device *pdev)
        struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
        struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
        struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio;
-       int irq = platform_get_irq(pdev, 0);
        int ret;
 
        if (pdata && pdata->remove)
@@ -405,10 +325,6 @@ static int tc3589x_gpio_remove(struct platform_device *pdev)
                return ret;
        }
 
-       free_irq(irq, tc3589x_gpio);
-
-       kfree(tc3589x_gpio);
-
        return 0;
 }
 
index 2b49f878b56c69c8f28897dbc5c99d59daa09f91..4e8fb8261a8754cdfee323adad33d7218e951444 100644 (file)
@@ -408,7 +408,7 @@ static struct tegra_gpio_soc_config tegra30_gpio_config = {
        .upper_offset = 0x80,
 };
 
-static struct of_device_id tegra_gpio_of_match[] = {
+static const struct of_device_id tegra_gpio_of_match[] = {
        { .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config },
        { .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config },
        { },
@@ -458,10 +458,8 @@ static int tegra_gpio_probe(struct platform_device *pdev)
        tegra_gpio_banks = devm_kzalloc(&pdev->dev,
                        tegra_gpio_bank_count * sizeof(*tegra_gpio_banks),
                        GFP_KERNEL);
-       if (!tegra_gpio_banks) {
-               dev_err(&pdev->dev, "Couldn't allocate bank structure\n");
+       if (!tegra_gpio_banks)
                return -ENODEV;
-       }
 
        irq_domain = irq_domain_add_linear(pdev->dev.of_node,
                                           tegra_gpio_chip.ngpio,
index f9a8fbde108e3b424785a12bb5bc52dd06ac1551..efc7c129016d1d748f9c9a837956ced99cee0471 100644 (file)
@@ -224,6 +224,7 @@ static struct irq_chip timbgpio_irqchip = {
 static int timbgpio_probe(struct platform_device *pdev)
 {
        int err, i;
+       struct device *dev = &pdev->dev;
        struct gpio_chip *gc;
        struct timbgpio *tgpio;
        struct resource *iomem;
@@ -231,35 +232,35 @@ static int timbgpio_probe(struct platform_device *pdev)
        int irq = platform_get_irq(pdev, 0);
 
        if (!pdata || pdata->nr_pins > 32) {
-               err = -EINVAL;
-               goto err_mem;
+               dev_err(dev, "Invalid platform data\n");
+               return -EINVAL;
        }
 
        iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!iomem) {
-               err = -EINVAL;
-               goto err_mem;
+               dev_err(dev, "Unable to get resource\n");
+               return -EINVAL;
        }
 
-       tgpio = kzalloc(sizeof(*tgpio), GFP_KERNEL);
+       tgpio = devm_kzalloc(dev, sizeof(struct timbgpio), GFP_KERNEL);
        if (!tgpio) {
-               err = -EINVAL;
-               goto err_mem;
+               dev_err(dev, "Memory alloc failed\n");
+               return -EINVAL;
        }
        tgpio->irq_base = pdata->irq_base;
 
        spin_lock_init(&tgpio->lock);
 
-       if (!request_mem_region(iomem->start, resource_size(iomem),
-               DRIVER_NAME)) {
-               err = -EBUSY;
-               goto err_request;
+       if (!devm_request_mem_region(dev, iomem->start, resource_size(iomem),
+                                    DRIVER_NAME)) {
+               dev_err(dev, "Region already claimed\n");
+               return -EBUSY;
        }
 
-       tgpio->membase = ioremap(iomem->start, resource_size(iomem));
+       tgpio->membase = devm_ioremap(dev, iomem->start, resource_size(iomem));
        if (!tgpio->membase) {
-               err = -ENOMEM;
-               goto err_ioremap;
+               dev_err(dev, "Cannot ioremap\n");
+               return -ENOMEM;
        }
 
        gc = &tgpio->gpio;
@@ -279,7 +280,7 @@ static int timbgpio_probe(struct platform_device *pdev)
 
        err = gpiochip_add(gc);
        if (err)
-               goto err_chipadd;
+               return err;
 
        platform_set_drvdata(pdev, tgpio);
 
@@ -302,17 +303,6 @@ static int timbgpio_probe(struct platform_device *pdev)
        irq_set_chained_handler(irq, timbgpio_irq);
 
        return 0;
-
-err_chipadd:
-       iounmap(tgpio->membase);
-err_ioremap:
-       release_mem_region(iomem->start, resource_size(iomem));
-err_request:
-       kfree(tgpio);
-err_mem:
-       printk(KERN_ERR DRIVER_NAME": Failed to register GPIOs: %d\n", err);
-
-       return err;
 }
 
 static int timbgpio_remove(struct platform_device *pdev)
@@ -320,7 +310,6 @@ static int timbgpio_remove(struct platform_device *pdev)
        int err;
        struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct timbgpio *tgpio = platform_get_drvdata(pdev);
-       struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        int irq = platform_get_irq(pdev, 0);
 
        if (irq >= 0 && tgpio->irq_base > 0) {
@@ -338,10 +327,6 @@ static int timbgpio_remove(struct platform_device *pdev)
        if (err)
                printk(KERN_ERR DRIVER_NAME": failed to remove gpio_chip\n");
 
-       iounmap(tgpio->membase);
-       release_mem_region(iomem->start, resource_size(iomem));
-       kfree(tgpio);
-
        return 0;
 }
 
index 8994dfa13491bd0bb2a94ac6c72606b61c572e30..a69fbea41253877566f19c41706c08c97c813837 100644 (file)
@@ -97,10 +97,8 @@ static int tps6586x_gpio_probe(struct platform_device *pdev)
        pdata = dev_get_platdata(pdev->dev.parent);
        tps6586x_gpio = devm_kzalloc(&pdev->dev,
                                sizeof(*tps6586x_gpio), GFP_KERNEL);
-       if (!tps6586x_gpio) {
-               dev_err(&pdev->dev, "Could not allocate tps6586x_gpio\n");
+       if (!tps6586x_gpio)
                return -ENOMEM;
-       }
 
        tps6586x_gpio->parent = pdev->dev.parent;
 
index b6e818e680076c2041469d47e4ff03f7d7dee8c0..e2f8cda235ead0bcb3616ab63775d18d6ac55eac 100644 (file)
@@ -123,10 +123,8 @@ static int tps65910_gpio_probe(struct platform_device *pdev)
 
        tps65910_gpio = devm_kzalloc(&pdev->dev,
                                sizeof(*tps65910_gpio), GFP_KERNEL);
-       if (!tps65910_gpio) {
-               dev_err(&pdev->dev, "Could not allocate tps65910_gpio\n");
+       if (!tps65910_gpio)
                return -ENOMEM;
-       }
 
        tps65910_gpio->tps65910 = tps65910;
 
index 792a05ad46497126e39c4ed23bc240bf3b63e66b..12481867daf11e8fa580df58e266225d9e332ade 100644 (file)
@@ -289,7 +289,7 @@ static int xgpio_of_probe(struct device_node *np)
        return 0;
 }
 
-static struct of_device_id xgpio_of_match[] = {
+static const struct of_device_id xgpio_of_match[] = {
        { .compatible = "xlnx,xps-gpio-1.00.a", },
        { /* end of list */ },
 };
index 9bf5034b6cdb61bc14f85fc98b090690190eaaa1..54e54e4cc6c44715206860022797e2b24792b8fa 100644 (file)
@@ -81,9 +81,15 @@ static inline void zevio_gpio_port_set(struct zevio_gpio *c, unsigned pin,
 static int zevio_gpio_get(struct gpio_chip *chip, unsigned pin)
 {
        struct zevio_gpio *controller = to_zevio_gpio(chip);
+       u32 val, dir;
 
-       /* Only reading allowed, so no spinlock needed */
-       u32 val = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_INPUT);
+       spin_lock(&controller->lock);
+       dir = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_DIRECTION);
+       if (dir & BIT(ZEVIO_GPIO_BIT(pin)))
+               val = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_INPUT);
+       else
+               val = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_OUTPUT);
+       spin_unlock(&controller->lock);
 
        return (val >> ZEVIO_GPIO_BIT(pin)) & 0x1;
 }
@@ -172,10 +178,8 @@ static int zevio_gpio_probe(struct platform_device *pdev)
        int status, i;
 
        controller = devm_kzalloc(&pdev->dev, sizeof(*controller), GFP_KERNEL);
-       if (!controller) {
-               dev_err(&pdev->dev, "not enough free memory\n");
+       if (!controller)
                return -ENOMEM;
-       }
 
        /* Copy our reference */
        controller->chip.gc = zevio_gpio_chip;
@@ -198,7 +202,7 @@ static int zevio_gpio_probe(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id zevio_gpio_of_match[] = {
+static const struct of_device_id zevio_gpio_of_match[] = {
        { .compatible = "lsi,zevio-gpio", },
        { },
 };
@@ -209,7 +213,7 @@ static struct platform_driver zevio_gpio_driver = {
        .driver         = {
                .name   = "gpio-zevio",
                .owner  = THIS_MODULE,
-               .of_match_table = of_match_ptr(zevio_gpio_of_match),
+               .of_match_table = zevio_gpio_of_match,
        },
        .probe          = zevio_gpio_probe,
 };
index 401add28933f4f6f39c70b626e081ec39aef554b..4a987917c1862279756e844e58db98bad38dbdd7 100644 (file)
@@ -449,9 +449,10 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
                mutex_unlock(&achip->conn_lock);
 
                if (function == ACPI_WRITE)
-                       gpiod_set_raw_value(desc, !!((1 << i) & *value));
+                       gpiod_set_raw_value_cansleep(desc,
+                                                    !!((1 << i) & *value));
                else
-                       *value |= (u64)gpiod_get_raw_value(desc) << i;
+                       *value |= (u64)gpiod_get_raw_value_cansleep(desc) << i;
        }
 
 out:
index 2024d45e5503624ba7c1b9ff7d75f91fb4e912e1..af7e25c9a9ae6d56d5765870f233830c7b4a9e5a 100644 (file)
@@ -48,7 +48,7 @@ static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data)
        if (ret < 0)
                return false;
 
-       gg_data->out_gpio = gpio_to_desc(ret + gc->base);
+       gg_data->out_gpio = gpiochip_get_desc(gc, ret);
        return true;
 }
 
@@ -96,6 +96,20 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
 }
 EXPORT_SYMBOL(of_get_named_gpiod_flags);
 
+int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
+                           int index, enum of_gpio_flags *flags)
+{
+       struct gpio_desc *desc;
+
+       desc = of_get_named_gpiod_flags(np, list_name, index, flags);
+
+       if (IS_ERR(desc))
+               return PTR_ERR(desc);
+       else
+               return desc_to_gpio(desc);
+}
+EXPORT_SYMBOL(of_get_named_gpio_flags);
+
 /**
  * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags
  * @gc:                pointer to the gpio_chip structure
index f48817d974802c3ec771814bef84bc97ab6039b5..d9c9cb4665dbf8899d3fe5b7ce9269b3fdee5961 100644 (file)
@@ -1363,6 +1363,11 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
                                  int parent_irq,
                                  irq_flow_handler_t parent_handler)
 {
+       if (gpiochip->can_sleep) {
+               chip_err(gpiochip, "you cannot have chained interrupts on a chip that may sleep\n");
+               return;
+       }
+
        irq_set_chained_handler(parent_irq, parent_handler);
        /*
         * The parent irqchip is already using the chip_data for this
@@ -1372,6 +1377,12 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
 }
 EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip);
 
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpiochip_irq_lock_class;
+
 /**
  * gpiochip_irq_map() - maps an IRQ into a GPIO irqchip
  * @d: the irqdomain used by this irqchip
@@ -1388,22 +1399,35 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
        struct gpio_chip *chip = d->host_data;
 
        irq_set_chip_data(irq, chip);
+       irq_set_lockdep_class(irq, &gpiochip_irq_lock_class);
        irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler);
+       /* Chips that can sleep need nested thread handlers */
+       if (chip->can_sleep)
+               irq_set_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
        set_irq_flags(irq, IRQF_VALID);
 #else
        irq_set_noprobe(irq);
 #endif
-       irq_set_irq_type(irq, chip->irq_default_type);
+       /*
+        * No set-up of the hardware will happen if IRQ_TYPE_NONE
+        * is passed as default type.
+        */
+       if (chip->irq_default_type != IRQ_TYPE_NONE)
+               irq_set_irq_type(irq, chip->irq_default_type);
 
        return 0;
 }
 
 static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)
 {
+       struct gpio_chip *chip = d->host_data;
+
 #ifdef CONFIG_ARM
        set_irq_flags(irq, 0);
 #endif
+       if (chip->can_sleep)
+               irq_set_nested_thread(irq, 0);
        irq_set_chip_and_handler(irq, NULL, NULL);
        irq_set_chip_data(irq, NULL);
 }
@@ -1471,7 +1495,8 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
  * @first_irq: if not dynamically assigned, the base (first) IRQ to
  * allocate gpiochip irqs from
  * @handler: the irq handler to use (often a predefined irq core function)
- * @type: the default type for IRQs on this irqchip
+ * @type: the default type for IRQs on this irqchip, pass IRQ_TYPE_NONE
+ * to have the core avoid setting up any default type in the hardware.
  *
  * This function closely associates a certain irqchip with a certain
  * gpiochip, providing an irq domain to translate the local IRQs to
@@ -2571,22 +2596,27 @@ void gpiod_add_lookup_table(struct gpiod_lookup_table *table)
        mutex_unlock(&gpio_lookup_lock);
 }
 
-#ifdef CONFIG_OF
 static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
                                      unsigned int idx,
                                      enum gpio_lookup_flags *flags)
 {
+       static const char *suffixes[] = { "gpios", "gpio" };
        char prop_name[32]; /* 32 is max size of property name */
        enum of_gpio_flags of_flags;
        struct gpio_desc *desc;
+       unsigned int i;
 
-       if (con_id)
-               snprintf(prop_name, 32, "%s-gpios", con_id);
-       else
-               snprintf(prop_name, 32, "gpios");
+       for (i = 0; i < ARRAY_SIZE(suffixes); i++) {
+               if (con_id)
+                       snprintf(prop_name, 32, "%s-%s", con_id, suffixes[i]);
+               else
+                       snprintf(prop_name, 32, "%s", suffixes[i]);
 
-       desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx,
-                                       &of_flags);
+               desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx,
+                                               &of_flags);
+               if (!IS_ERR(desc))
+                       break;
+       }
 
        if (IS_ERR(desc))
                return desc;
@@ -2596,14 +2626,6 @@ static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
 
        return desc;
 }
-#else
-static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
-                                     unsigned int idx,
-                                     enum gpio_lookup_flags *flags)
-{
-       return ERR_PTR(-ENODEV);
-}
-#endif
 
 static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
                                        unsigned int idx,
@@ -2701,7 +2723,7 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
 }
 
 /**
- * gpio_get - obtain a GPIO for a given GPIO function
+ * gpiod_get - obtain a GPIO for a given GPIO function
  * @dev:       GPIO consumer, can be NULL for system-global GPIOs
  * @con_id:    function within the GPIO consumer
  *
@@ -2715,6 +2737,22 @@ struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id)
 }
 EXPORT_SYMBOL_GPL(gpiod_get);
 
+/**
+ * gpiod_get_optional - obtain an optional GPIO for a given GPIO function
+ * @dev: GPIO consumer, can be NULL for system-global GPIOs
+ * @con_id: function within the GPIO consumer
+ *
+ * This is equivalent to gpiod_get(), except that when no GPIO was assigned to
+ * the requested function it will return NULL. This is convenient for drivers
+ * that need to handle optional GPIOs.
+ */
+struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
+                                                 const char *con_id)
+{
+       return gpiod_get_index_optional(dev, con_id, 0);
+}
+EXPORT_SYMBOL_GPL(gpiod_get_optional);
+
 /**
  * gpiod_get_index - obtain a GPIO from a multi-index GPIO function
  * @dev:       GPIO consumer, can be NULL for system-global GPIOs
@@ -2777,6 +2815,33 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(gpiod_get_index);
 
+/**
+ * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO
+ *                            function
+ * @dev: GPIO consumer, can be NULL for system-global GPIOs
+ * @con_id: function within the GPIO consumer
+ * @index: index of the GPIO to obtain in the consumer
+ *
+ * This is equivalent to gpiod_get_index(), except that when no GPIO with the
+ * specified index was assigned to the requested function it will return NULL.
+ * This is convenient for drivers that need to handle optional GPIOs.
+ */
+struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev,
+                                                       const char *con_id,
+                                                       unsigned int index)
+{
+       struct gpio_desc *desc;
+
+       desc = gpiod_get_index(dev, con_id, index);
+       if (IS_ERR(desc)) {
+               if (PTR_ERR(desc) == -ENOENT)
+                       return NULL;
+       }
+
+       return desc;
+}
+EXPORT_SYMBOL_GPL(gpiod_get_index_optional);
+
 /**
  * gpiod_put - dispose of a GPIO descriptor
  * @desc:      GPIO descriptor to dispose of
index cf092941a9fdda28f6ec3b58ab97f49e5dd963c8..1a4103dd38df4695a35a316d4903fabc872aaec0 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/err.h>
 #include <linux/device.h>
 
+enum of_gpio_flags;
+
 /**
  * struct acpi_gpio_info - ACPI GPIO specific information
  * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo
@@ -46,4 +48,7 @@ acpi_get_gpiod_by_index(struct device *dev, int index,
 int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label);
 void gpiochip_free_own_desc(struct gpio_desc *desc);
 
+struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
+                  const char *list_name, int index, enum of_gpio_flags *flags);
+
 #endif /* GPIOLIB_H */
index 96177eec0a0eb9a879493a54c79b3613f0bb9b34..eedb023af27d705b7ddd23727093b17baf5352c8 100644 (file)
@@ -1833,7 +1833,6 @@ int i915_driver_unload(struct drm_device *dev)
                flush_workqueue(dev_priv->wq);
 
                mutex_lock(&dev->struct_mutex);
-               i915_gem_free_all_phys_object(dev);
                i915_gem_cleanup_ringbuffer(dev);
                i915_gem_context_fini(dev);
                WARN_ON(dev_priv->mm.aliasing_ppgtt);
index ec82f6bff1225dc06e5b591838c59778f65cecb5..388c028e223ccbcad3bf1c15d8bbd1f09be3719d 100644 (file)
@@ -242,18 +242,6 @@ struct intel_ddi_plls {
 #define WATCH_LISTS    0
 #define WATCH_GTT      0
 
-#define I915_GEM_PHYS_CURSOR_0 1
-#define I915_GEM_PHYS_CURSOR_1 2
-#define I915_GEM_PHYS_OVERLAY_REGS 3
-#define I915_MAX_PHYS_OBJECT (I915_GEM_PHYS_OVERLAY_REGS)
-
-struct drm_i915_gem_phys_object {
-       int id;
-       struct page **page_list;
-       drm_dma_handle_t *handle;
-       struct drm_i915_gem_object *cur_obj;
-};
-
 struct opregion_header;
 struct opregion_acpi;
 struct opregion_swsci;
@@ -1187,9 +1175,6 @@ struct i915_gem_mm {
        /** Bit 6 swizzling required for Y tiling */
        uint32_t bit_6_swizzle_y;
 
-       /* storage for physical objects */
-       struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT];
-
        /* accounting, useful for userland debugging */
        spinlock_t object_stat_lock;
        size_t object_memory;
@@ -1769,7 +1754,7 @@ struct drm_i915_gem_object {
        struct drm_file *pin_filp;
 
        /** for phy allocated objects */
-       struct drm_i915_gem_phys_object *phys_obj;
+       drm_dma_handle_t *phys_handle;
 };
 
 #define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base)
@@ -1954,6 +1939,9 @@ struct drm_i915_cmd_table {
 #define IS_ULT(dev)            (IS_HSW_ULT(dev) || IS_BDW_ULT(dev))
 #define IS_HSW_GT3(dev)                (IS_HASWELL(dev) && \
                                 ((dev)->pdev->device & 0x00F0) == 0x0020)
+/* ULX machines are also considered ULT. */
+#define IS_HSW_ULX(dev)                ((dev)->pdev->device == 0x0A0E || \
+                                (dev)->pdev->device == 0x0A1E)
 #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary)
 
 /*
@@ -2201,10 +2189,12 @@ void i915_gem_vma_destroy(struct i915_vma *vma);
 #define PIN_MAPPABLE 0x1
 #define PIN_NONBLOCK 0x2
 #define PIN_GLOBAL 0x4
+#define PIN_OFFSET_BIAS 0x8
+#define PIN_OFFSET_MASK (~4095)
 int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj,
                                     struct i915_address_space *vm,
                                     uint32_t alignment,
-                                    unsigned flags);
+                                    uint64_t flags);
 int __must_check i915_vma_unbind(struct i915_vma *vma);
 int i915_gem_object_put_pages(struct drm_i915_gem_object *obj);
 void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv);
@@ -2331,13 +2321,8 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
                                     u32 alignment,
                                     struct intel_ring_buffer *pipelined);
 void i915_gem_object_unpin_from_display_plane(struct drm_i915_gem_object *obj);
-int i915_gem_attach_phys_object(struct drm_device *dev,
-                               struct drm_i915_gem_object *obj,
-                               int id,
+int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj,
                                int align);
-void i915_gem_detach_phys_object(struct drm_device *dev,
-                                struct drm_i915_gem_object *obj);
-void i915_gem_free_all_phys_object(struct drm_device *dev);
 int i915_gem_open(struct drm_device *dev, struct drm_file *file);
 void i915_gem_release(struct drm_device *dev, struct drm_file *file);
 
@@ -2462,6 +2447,8 @@ int __must_check i915_gem_evict_something(struct drm_device *dev,
                                          int min_size,
                                          unsigned alignment,
                                          unsigned cache_level,
+                                         unsigned long start,
+                                         unsigned long end,
                                          unsigned flags);
 int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle);
 int i915_gem_evict_everything(struct drm_device *dev);
index 2871ce75f438641b34bef7749545d4fedfde5744..3326770c9ed2618d914d931a8fd5b54b2137c02b 100644 (file)
@@ -43,10 +43,6 @@ static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *o
 static __must_check int
 i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
                               bool readonly);
-static int i915_gem_phys_pwrite(struct drm_device *dev,
-                               struct drm_i915_gem_object *obj,
-                               struct drm_i915_gem_pwrite *args,
-                               struct drm_file *file);
 
 static void i915_gem_write_fence(struct drm_device *dev, int reg,
                                 struct drm_i915_gem_object *obj);
@@ -209,6 +205,128 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
        return 0;
 }
 
+static void i915_gem_object_detach_phys(struct drm_i915_gem_object *obj)
+{
+       drm_dma_handle_t *phys = obj->phys_handle;
+
+       if (!phys)
+               return;
+
+       if (obj->madv == I915_MADV_WILLNEED) {
+               struct address_space *mapping = file_inode(obj->base.filp)->i_mapping;
+               char *vaddr = phys->vaddr;
+               int i;
+
+               for (i = 0; i < obj->base.size / PAGE_SIZE; i++) {
+                       struct page *page = shmem_read_mapping_page(mapping, i);
+                       if (!IS_ERR(page)) {
+                               char *dst = kmap_atomic(page);
+                               memcpy(dst, vaddr, PAGE_SIZE);
+                               drm_clflush_virt_range(dst, PAGE_SIZE);
+                               kunmap_atomic(dst);
+
+                               set_page_dirty(page);
+                               mark_page_accessed(page);
+                               page_cache_release(page);
+                       }
+                       vaddr += PAGE_SIZE;
+               }
+               i915_gem_chipset_flush(obj->base.dev);
+       }
+
+#ifdef CONFIG_X86
+       set_memory_wb((unsigned long)phys->vaddr, phys->size / PAGE_SIZE);
+#endif
+       drm_pci_free(obj->base.dev, phys);
+       obj->phys_handle = NULL;
+}
+
+int
+i915_gem_object_attach_phys(struct drm_i915_gem_object *obj,
+                           int align)
+{
+       drm_dma_handle_t *phys;
+       struct address_space *mapping;
+       char *vaddr;
+       int i;
+
+       if (obj->phys_handle) {
+               if ((unsigned long)obj->phys_handle->vaddr & (align -1))
+                       return -EBUSY;
+
+               return 0;
+       }
+
+       if (obj->madv != I915_MADV_WILLNEED)
+               return -EFAULT;
+
+       if (obj->base.filp == NULL)
+               return -EINVAL;
+
+       /* create a new object */
+       phys = drm_pci_alloc(obj->base.dev, obj->base.size, align);
+       if (!phys)
+               return -ENOMEM;
+
+       vaddr = phys->vaddr;
+#ifdef CONFIG_X86
+       set_memory_wc((unsigned long)vaddr, phys->size / PAGE_SIZE);
+#endif
+       mapping = file_inode(obj->base.filp)->i_mapping;
+       for (i = 0; i < obj->base.size / PAGE_SIZE; i++) {
+               struct page *page;
+               char *src;
+
+               page = shmem_read_mapping_page(mapping, i);
+               if (IS_ERR(page)) {
+#ifdef CONFIG_X86
+                       set_memory_wb((unsigned long)phys->vaddr, phys->size / PAGE_SIZE);
+#endif
+                       drm_pci_free(obj->base.dev, phys);
+                       return PTR_ERR(page);
+               }
+
+               src = kmap_atomic(page);
+               memcpy(vaddr, src, PAGE_SIZE);
+               kunmap_atomic(src);
+
+               mark_page_accessed(page);
+               page_cache_release(page);
+
+               vaddr += PAGE_SIZE;
+       }
+
+       obj->phys_handle = phys;
+       return 0;
+}
+
+static int
+i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,
+                    struct drm_i915_gem_pwrite *args,
+                    struct drm_file *file_priv)
+{
+       struct drm_device *dev = obj->base.dev;
+       void *vaddr = obj->phys_handle->vaddr + args->offset;
+       char __user *user_data = to_user_ptr(args->data_ptr);
+
+       if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) {
+               unsigned long unwritten;
+
+               /* The physical object once assigned is fixed for the lifetime
+                * of the obj, so we can safely drop the lock and continue
+                * to access vaddr.
+                */
+               mutex_unlock(&dev->struct_mutex);
+               unwritten = copy_from_user(vaddr, user_data, args->size);
+               mutex_lock(&dev->struct_mutex);
+               if (unwritten)
+                       return -EFAULT;
+       }
+
+       i915_gem_chipset_flush(dev);
+       return 0;
+}
+
 void *i915_gem_object_alloc(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -921,8 +1039,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
         * pread/pwrite currently are reading and writing from the CPU
         * perspective, requiring manual detiling by the client.
         */
-       if (obj->phys_obj) {
-               ret = i915_gem_phys_pwrite(dev, obj, args, file);
+       if (obj->phys_handle) {
+               ret = i915_gem_phys_pwrite(obj, args, file);
                goto out;
        }
 
@@ -3208,12 +3326,14 @@ static struct i915_vma *
 i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
                           struct i915_address_space *vm,
                           unsigned alignment,
-                          unsigned flags)
+                          uint64_t flags)
 {
        struct drm_device *dev = obj->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 size, fence_size, fence_alignment, unfenced_alignment;
-       size_t gtt_max =
+       unsigned long start =
+               flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0;
+       unsigned long end =
                flags & PIN_MAPPABLE ? dev_priv->gtt.mappable_end : vm->total;
        struct i915_vma *vma;
        int ret;
@@ -3242,11 +3362,11 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
        /* If the object is bigger than the entire aperture, reject it early
         * before evicting everything in a vain attempt to find space.
         */
-       if (obj->base.size > gtt_max) {
-               DRM_DEBUG("Attempting to bind an object larger than the aperture: object=%zd > %s aperture=%zu\n",
+       if (obj->base.size > end) {
+               DRM_DEBUG("Attempting to bind an object larger than the aperture: object=%zd > %s aperture=%lu\n",
                          obj->base.size,
                          flags & PIN_MAPPABLE ? "mappable" : "total",
-                         gtt_max);
+                         end);
                return ERR_PTR(-E2BIG);
        }
 
@@ -3263,12 +3383,15 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
 search_free:
        ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node,
                                                  size, alignment,
-                                                 obj->cache_level, 0, gtt_max,
+                                                 obj->cache_level,
+                                                 start, end,
                                                  DRM_MM_SEARCH_DEFAULT,
                                                  DRM_MM_CREATE_DEFAULT);
        if (ret) {
                ret = i915_gem_evict_something(dev, vm, size, alignment,
-                                              obj->cache_level, flags);
+                                              obj->cache_level,
+                                              start, end,
+                                              flags);
                if (ret == 0)
                        goto search_free;
 
@@ -3828,11 +3951,30 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file)
        return ret;
 }
 
+static bool
+i915_vma_misplaced(struct i915_vma *vma, uint32_t alignment, uint64_t flags)
+{
+       struct drm_i915_gem_object *obj = vma->obj;
+
+       if (alignment &&
+           vma->node.start & (alignment - 1))
+               return true;
+
+       if (flags & PIN_MAPPABLE && !obj->map_and_fenceable)
+               return true;
+
+       if (flags & PIN_OFFSET_BIAS &&
+           vma->node.start < (flags & PIN_OFFSET_MASK))
+               return true;
+
+       return false;
+}
+
 int
 i915_gem_object_pin(struct drm_i915_gem_object *obj,
                    struct i915_address_space *vm,
                    uint32_t alignment,
-                   unsigned flags)
+                   uint64_t flags)
 {
        struct i915_vma *vma;
        int ret;
@@ -3845,15 +3987,13 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
                if (WARN_ON(vma->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT))
                        return -EBUSY;
 
-               if ((alignment &&
-                    vma->node.start & (alignment - 1)) ||
-                   (flags & PIN_MAPPABLE && !obj->map_and_fenceable)) {
+               if (i915_vma_misplaced(vma, alignment, flags)) {
                        WARN(vma->pin_count,
                             "bo is already pinned with incorrect alignment:"
                             " offset=%lx, req.alignment=%x, req.map_and_fenceable=%d,"
                             " obj->map_and_fenceable=%d\n",
                             i915_gem_obj_offset(obj, vm), alignment,
-                            flags & PIN_MAPPABLE,
+                            !!(flags & PIN_MAPPABLE),
                             obj->map_and_fenceable);
                        ret = i915_vma_unbind(vma);
                        if (ret)
@@ -4163,9 +4303,6 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 
        trace_i915_gem_object_destroy(obj);
 
-       if (obj->phys_obj)
-               i915_gem_detach_phys_object(dev, obj);
-
        list_for_each_entry_safe(vma, next, &obj->vma_list, vma_link) {
                int ret;
 
@@ -4183,6 +4320,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
                }
        }
 
+       i915_gem_object_detach_phys(obj);
+
        /* Stolen objects don't hold a ref, but do hold pin count. Fix that up
         * before progressing. */
        if (obj->stolen)
@@ -4646,190 +4785,6 @@ i915_gem_load(struct drm_device *dev)
        register_shrinker(&dev_priv->mm.inactive_shrinker);
 }
 
-/*
- * Create a physically contiguous memory object for this object
- * e.g. for cursor + overlay regs
- */
-static int i915_gem_init_phys_object(struct drm_device *dev,
-                                    int id, int size, int align)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_i915_gem_phys_object *phys_obj;
-       int ret;
-
-       if (dev_priv->mm.phys_objs[id - 1] || !size)
-               return 0;
-
-       phys_obj = kzalloc(sizeof(*phys_obj), GFP_KERNEL);
-       if (!phys_obj)
-               return -ENOMEM;
-
-       phys_obj->id = id;
-
-       phys_obj->handle = drm_pci_alloc(dev, size, align);
-       if (!phys_obj->handle) {
-               ret = -ENOMEM;
-               goto kfree_obj;
-       }
-#ifdef CONFIG_X86
-       set_memory_wc((unsigned long)phys_obj->handle->vaddr, phys_obj->handle->size / PAGE_SIZE);
-#endif
-
-       dev_priv->mm.phys_objs[id - 1] = phys_obj;
-
-       return 0;
-kfree_obj:
-       kfree(phys_obj);
-       return ret;
-}
-
-static void i915_gem_free_phys_object(struct drm_device *dev, int id)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_i915_gem_phys_object *phys_obj;
-
-       if (!dev_priv->mm.phys_objs[id - 1])
-               return;
-
-       phys_obj = dev_priv->mm.phys_objs[id - 1];
-       if (phys_obj->cur_obj) {
-               i915_gem_detach_phys_object(dev, phys_obj->cur_obj);
-       }
-
-#ifdef CONFIG_X86
-       set_memory_wb((unsigned long)phys_obj->handle->vaddr, phys_obj->handle->size / PAGE_SIZE);
-#endif
-       drm_pci_free(dev, phys_obj->handle);
-       kfree(phys_obj);
-       dev_priv->mm.phys_objs[id - 1] = NULL;
-}
-
-void i915_gem_free_all_phys_object(struct drm_device *dev)
-{
-       int i;
-
-       for (i = I915_GEM_PHYS_CURSOR_0; i <= I915_MAX_PHYS_OBJECT; i++)
-               i915_gem_free_phys_object(dev, i);
-}
-
-void i915_gem_detach_phys_object(struct drm_device *dev,
-                                struct drm_i915_gem_object *obj)
-{
-       struct address_space *mapping = file_inode(obj->base.filp)->i_mapping;
-       char *vaddr;
-       int i;
-       int page_count;
-
-       if (!obj->phys_obj)
-               return;
-       vaddr = obj->phys_obj->handle->vaddr;
-
-       page_count = obj->base.size / PAGE_SIZE;
-       for (i = 0; i < page_count; i++) {
-               struct page *page = shmem_read_mapping_page(mapping, i);
-               if (!IS_ERR(page)) {
-                       char *dst = kmap_atomic(page);
-                       memcpy(dst, vaddr + i*PAGE_SIZE, PAGE_SIZE);
-                       kunmap_atomic(dst);
-
-                       drm_clflush_pages(&page, 1);
-
-                       set_page_dirty(page);
-                       mark_page_accessed(page);
-                       page_cache_release(page);
-               }
-       }
-       i915_gem_chipset_flush(dev);
-
-       obj->phys_obj->cur_obj = NULL;
-       obj->phys_obj = NULL;
-}
-
-int
-i915_gem_attach_phys_object(struct drm_device *dev,
-                           struct drm_i915_gem_object *obj,
-                           int id,
-                           int align)
-{
-       struct address_space *mapping = file_inode(obj->base.filp)->i_mapping;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int ret = 0;
-       int page_count;
-       int i;
-
-       if (id > I915_MAX_PHYS_OBJECT)
-               return -EINVAL;
-
-       if (obj->phys_obj) {
-               if (obj->phys_obj->id == id)
-                       return 0;
-               i915_gem_detach_phys_object(dev, obj);
-       }
-
-       /* create a new object */
-       if (!dev_priv->mm.phys_objs[id - 1]) {
-               ret = i915_gem_init_phys_object(dev, id,
-                                               obj->base.size, align);
-               if (ret) {
-                       DRM_ERROR("failed to init phys object %d size: %zu\n",
-                                 id, obj->base.size);
-                       return ret;
-               }
-       }
-
-       /* bind to the object */
-       obj->phys_obj = dev_priv->mm.phys_objs[id - 1];
-       obj->phys_obj->cur_obj = obj;
-
-       page_count = obj->base.size / PAGE_SIZE;
-
-       for (i = 0; i < page_count; i++) {
-               struct page *page;
-               char *dst, *src;
-
-               page = shmem_read_mapping_page(mapping, i);
-               if (IS_ERR(page))
-                       return PTR_ERR(page);
-
-               src = kmap_atomic(page);
-               dst = obj->phys_obj->handle->vaddr + (i * PAGE_SIZE);
-               memcpy(dst, src, PAGE_SIZE);
-               kunmap_atomic(src);
-
-               mark_page_accessed(page);
-               page_cache_release(page);
-       }
-
-       return 0;
-}
-
-static int
-i915_gem_phys_pwrite(struct drm_device *dev,
-                    struct drm_i915_gem_object *obj,
-                    struct drm_i915_gem_pwrite *args,
-                    struct drm_file *file_priv)
-{
-       void *vaddr = obj->phys_obj->handle->vaddr + args->offset;
-       char __user *user_data = to_user_ptr(args->data_ptr);
-
-       if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) {
-               unsigned long unwritten;
-
-               /* The physical object once assigned is fixed for the lifetime
-                * of the obj, so we can safely drop the lock and continue
-                * to access vaddr.
-                */
-               mutex_unlock(&dev->struct_mutex);
-               unwritten = copy_from_user(vaddr, user_data, args->size);
-               mutex_lock(&dev->struct_mutex);
-               if (unwritten)
-                       return -EFAULT;
-       }
-
-       i915_gem_chipset_flush(dev);
-       return 0;
-}
-
 void i915_gem_release(struct drm_device *dev, struct drm_file *file)
 {
        struct drm_i915_file_private *file_priv = file->driver_priv;
index 75fca63dc8c15b297f6b528dcb2b21327241d063..bbf4b12d842effa7972e7dcaaa23e1de08434b59 100644 (file)
@@ -68,9 +68,9 @@ mark_free(struct i915_vma *vma, struct list_head *unwind)
 int
 i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
                         int min_size, unsigned alignment, unsigned cache_level,
+                        unsigned long start, unsigned long end,
                         unsigned flags)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct list_head eviction_list, unwind_list;
        struct i915_vma *vma;
        int ret = 0;
@@ -102,11 +102,10 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
         */
 
        INIT_LIST_HEAD(&unwind_list);
-       if (flags & PIN_MAPPABLE) {
-               BUG_ON(!i915_is_ggtt(vm));
+       if (start != 0 || end != vm->total) {
                drm_mm_init_scan_with_range(&vm->mm, min_size,
-                                           alignment, cache_level, 0,
-                                           dev_priv->gtt.mappable_end);
+                                           alignment, cache_level,
+                                           start, end);
        } else
                drm_mm_init_scan(&vm->mm, min_size, alignment, cache_level);
 
index 2c9d9cbaf653307aff52e037f596f4343219a3ee..20fef6c502676b2c82bdd19cbe343f5f864b0ccc 100644 (file)
@@ -35,6 +35,9 @@
 
 #define  __EXEC_OBJECT_HAS_PIN (1<<31)
 #define  __EXEC_OBJECT_HAS_FENCE (1<<30)
+#define  __EXEC_OBJECT_NEEDS_BIAS (1<<28)
+
+#define BATCH_OFFSET_BIAS (256*1024)
 
 struct eb_vmas {
        struct list_head vmas;
@@ -545,7 +548,7 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
        struct drm_i915_gem_exec_object2 *entry = vma->exec_entry;
        bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
        bool need_fence;
-       unsigned flags;
+       uint64_t flags;
        int ret;
 
        flags = 0;
@@ -559,6 +562,8 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
 
        if (entry->flags & EXEC_OBJECT_NEEDS_GTT)
                flags |= PIN_GLOBAL;
+       if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS)
+               flags |= BATCH_OFFSET_BIAS | PIN_OFFSET_BIAS;
 
        ret = i915_gem_object_pin(obj, vma->vm, entry->alignment, flags);
        if (ret)
@@ -592,6 +597,36 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
        return 0;
 }
 
+static bool
+eb_vma_misplaced(struct i915_vma *vma, bool has_fenced_gpu_access)
+{
+       struct drm_i915_gem_exec_object2 *entry = vma->exec_entry;
+       struct drm_i915_gem_object *obj = vma->obj;
+       bool need_fence, need_mappable;
+
+       need_fence =
+               has_fenced_gpu_access &&
+               entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
+               obj->tiling_mode != I915_TILING_NONE;
+       need_mappable = need_fence || need_reloc_mappable(vma);
+
+       WARN_ON((need_mappable || need_fence) &&
+              !i915_is_ggtt(vma->vm));
+
+       if (entry->alignment &&
+           vma->node.start & (entry->alignment - 1))
+               return true;
+
+       if (need_mappable && !obj->map_and_fenceable)
+               return true;
+
+       if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS &&
+           vma->node.start < BATCH_OFFSET_BIAS)
+               return true;
+
+       return false;
+}
+
 static int
 i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
                            struct list_head *vmas,
@@ -653,26 +688,10 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
 
                /* Unbind any ill-fitting objects or pin. */
                list_for_each_entry(vma, vmas, exec_list) {
-                       struct drm_i915_gem_exec_object2 *entry = vma->exec_entry;
-                       bool need_fence, need_mappable;
-
-                       obj = vma->obj;
-
                        if (!drm_mm_node_allocated(&vma->node))
                                continue;
 
-                       need_fence =
-                               has_fenced_gpu_access &&
-                               entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
-                               obj->tiling_mode != I915_TILING_NONE;
-                       need_mappable = need_fence || need_reloc_mappable(vma);
-
-                       WARN_ON((need_mappable || need_fence) &&
-                              !i915_is_ggtt(vma->vm));
-
-                       if ((entry->alignment &&
-                            vma->node.start & (entry->alignment - 1)) ||
-                           (need_mappable && !obj->map_and_fenceable))
+                       if (eb_vma_misplaced(vma, has_fenced_gpu_access))
                                ret = i915_vma_unbind(vma);
                        else
                                ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs);
@@ -773,9 +792,9 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
                 * relocations were valid.
                 */
                for (j = 0; j < exec[i].relocation_count; j++) {
-                       if (copy_to_user(&user_relocs[j].presumed_offset,
-                                        &invalid_offset,
-                                        sizeof(invalid_offset))) {
+                       if (__copy_to_user(&user_relocs[j].presumed_offset,
+                                          &invalid_offset,
+                                          sizeof(invalid_offset))) {
                                ret = -EFAULT;
                                mutex_lock(&dev->struct_mutex);
                                goto err;
@@ -999,6 +1018,25 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev,
        return 0;
 }
 
+static struct drm_i915_gem_object *
+eb_get_batch(struct eb_vmas *eb)
+{
+       struct i915_vma *vma = list_entry(eb->vmas.prev, typeof(*vma), exec_list);
+
+       /*
+        * SNA is doing fancy tricks with compressing batch buffers, which leads
+        * to negative relocation deltas. Usually that works out ok since the
+        * relocate address is still positive, except when the batch is placed
+        * very low in the GTT. Ensure this doesn't happen.
+        *
+        * Note that actual hangs have only been observed on gen7, but for
+        * paranoia do it everywhere.
+        */
+       vma->exec_entry->flags |= __EXEC_OBJECT_NEEDS_BIAS;
+
+       return vma->obj;
+}
+
 static int
 i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                       struct drm_file *file,
@@ -1153,7 +1191,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                goto err;
 
        /* take note of the batch buffer before we might reorder the lists */
-       batch_obj = list_entry(eb->vmas.prev, struct i915_vma, exec_list)->obj;
+       batch_obj = eb_get_batch(eb);
 
        /* Move the objects en-masse into the GTT, evicting if necessary. */
        need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0;
@@ -1355,18 +1393,21 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
 
        ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list);
        if (!ret) {
+               struct drm_i915_gem_exec_object __user *user_exec_list =
+                       to_user_ptr(args->buffers_ptr);
+
                /* Copy the new buffer offsets back to the user's exec list. */
-               for (i = 0; i < args->buffer_count; i++)
-                       exec_list[i].offset = exec2_list[i].offset;
-               /* ... and back out to userspace */
-               ret = copy_to_user(to_user_ptr(args->buffers_ptr),
-                                  exec_list,
-                                  sizeof(*exec_list) * args->buffer_count);
-               if (ret) {
-                       ret = -EFAULT;
-                       DRM_DEBUG("failed to copy %d exec entries "
-                                 "back to user (%d)\n",
-                                 args->buffer_count, ret);
+               for (i = 0; i < args->buffer_count; i++) {
+                       ret = __copy_to_user(&user_exec_list[i].offset,
+                                            &exec2_list[i].offset,
+                                            sizeof(user_exec_list[i].offset));
+                       if (ret) {
+                               ret = -EFAULT;
+                               DRM_DEBUG("failed to copy %d exec entries "
+                                         "back to user (%d)\n",
+                                         args->buffer_count, ret);
+                               break;
+                       }
                }
        }
 
@@ -1412,14 +1453,21 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
        ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list);
        if (!ret) {
                /* Copy the new buffer offsets back to the user's exec list. */
-               ret = copy_to_user(to_user_ptr(args->buffers_ptr),
-                                  exec2_list,
-                                  sizeof(*exec2_list) * args->buffer_count);
-               if (ret) {
-                       ret = -EFAULT;
-                       DRM_DEBUG("failed to copy %d exec entries "
-                                 "back to user (%d)\n",
-                                 args->buffer_count, ret);
+               struct drm_i915_gem_exec_object2 *user_exec_list =
+                                  to_user_ptr(args->buffers_ptr);
+               int i;
+
+               for (i = 0; i < args->buffer_count; i++) {
+                       ret = __copy_to_user(&user_exec_list[i].offset,
+                                            &exec2_list[i].offset,
+                                            sizeof(user_exec_list[i].offset));
+                       if (ret) {
+                               ret = -EFAULT;
+                               DRM_DEBUG("failed to copy %d exec entries "
+                                         "back to user\n",
+                                         args->buffer_count);
+                               break;
+                       }
                }
        }
 
index 62a5c3627b90eaea4e6620cb829af572781e3d94..5deb22864c522a6513de4c49742e725eef987d9b 100644 (file)
@@ -34,25 +34,35 @@ static void gen8_setup_private_ppat(struct drm_i915_private *dev_priv);
 
 bool intel_enable_ppgtt(struct drm_device *dev, bool full)
 {
-       if (i915.enable_ppgtt == 0 || !HAS_ALIASING_PPGTT(dev))
+       if (i915.enable_ppgtt == 0)
                return false;
 
        if (i915.enable_ppgtt == 1 && full)
                return false;
 
+       return true;
+}
+
+static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt)
+{
+       if (enable_ppgtt == 0 || !HAS_ALIASING_PPGTT(dev))
+               return 0;
+
+       if (enable_ppgtt == 1)
+               return 1;
+
+       if (enable_ppgtt == 2 && HAS_PPGTT(dev))
+               return 2;
+
 #ifdef CONFIG_INTEL_IOMMU
        /* Disable ppgtt on SNB if VT-d is on. */
        if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped) {
                DRM_INFO("Disabling PPGTT because VT-d is on\n");
-               return false;
+               return 0;
        }
 #endif
 
-       /* Full ppgtt disabled by default for now due to issues. */
-       if (full)
-               return HAS_PPGTT(dev) && (i915.enable_ppgtt == 2);
-       else
-               return HAS_ALIASING_PPGTT(dev);
+       return HAS_ALIASING_PPGTT(dev) ? 1 : 0;
 }
 
 #define GEN6_PPGTT_PD_ENTRIES 512
@@ -1079,7 +1089,9 @@ alloc:
        if (ret == -ENOSPC && !retried) {
                ret = i915_gem_evict_something(dev, &dev_priv->gtt.base,
                                               GEN6_PD_SIZE, GEN6_PD_ALIGN,
-                                              I915_CACHE_NONE, 0);
+                                              I915_CACHE_NONE,
+                                              0, dev_priv->gtt.base.total,
+                                              0);
                if (ret)
                        return ret;
 
@@ -2031,6 +2043,14 @@ int i915_gem_gtt_init(struct drm_device *dev)
                 gtt->base.total >> 20);
        DRM_DEBUG_DRIVER("GMADR size = %ldM\n", gtt->mappable_end >> 20);
        DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n", gtt->stolen_size >> 20);
+       /*
+        * i915.enable_ppgtt is read-only, so do an early pass to validate the
+        * user's requested state against the hardware/driver capabilities.  We
+        * do this now so that we can print out any log messages once rather
+        * than every time we check intel_enable_ppgtt().
+        */
+       i915.enable_ppgtt = sanitize_enable_ppgtt(dev, i915.enable_ppgtt);
+       DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915.enable_ppgtt);
 
        return 0;
 }
index fa486c5fbb0250650b558632c6f63aa0ebf5bd63..aff4a113cda3c0cd724d3b4d13ce0fb8bbc48313 100644 (file)
@@ -560,47 +560,71 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
 
        dev_priv->vbt.edp_pps = *edp_pps;
 
-       dev_priv->vbt.edp_rate = edp_link_params->rate ? DP_LINK_BW_2_7 :
-               DP_LINK_BW_1_62;
+       switch (edp_link_params->rate) {
+       case EDP_RATE_1_62:
+               dev_priv->vbt.edp_rate = DP_LINK_BW_1_62;
+               break;
+       case EDP_RATE_2_7:
+               dev_priv->vbt.edp_rate = DP_LINK_BW_2_7;
+               break;
+       default:
+               DRM_DEBUG_KMS("VBT has unknown eDP link rate value %u\n",
+                             edp_link_params->rate);
+               break;
+       }
+
        switch (edp_link_params->lanes) {
-       case 0:
+       case EDP_LANE_1:
                dev_priv->vbt.edp_lanes = 1;
                break;
-       case 1:
+       case EDP_LANE_2:
                dev_priv->vbt.edp_lanes = 2;
                break;
-       case 3:
-       default:
+       case EDP_LANE_4:
                dev_priv->vbt.edp_lanes = 4;
                break;
+       default:
+               DRM_DEBUG_KMS("VBT has unknown eDP lane count value %u\n",
+                             edp_link_params->lanes);
+               break;
        }
+
        switch (edp_link_params->preemphasis) {
-       case 0:
+       case EDP_PREEMPHASIS_NONE:
                dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_0;
                break;
-       case 1:
+       case EDP_PREEMPHASIS_3_5dB:
                dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_3_5;
                break;
-       case 2:
+       case EDP_PREEMPHASIS_6dB:
                dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_6;
                break;
-       case 3:
+       case EDP_PREEMPHASIS_9_5dB:
                dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPHASIS_9_5;
                break;
+       default:
+               DRM_DEBUG_KMS("VBT has unknown eDP pre-emphasis value %u\n",
+                             edp_link_params->preemphasis);
+               break;
        }
+
        switch (edp_link_params->vswing) {
-       case 0:
+       case EDP_VSWING_0_4V:
                dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_400;
                break;
-       case 1:
+       case EDP_VSWING_0_6V:
                dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_600;
                break;
-       case 2:
+       case EDP_VSWING_0_8V:
                dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_800;
                break;
-       case 3:
+       case EDP_VSWING_1_2V:
                dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_1200;
                break;
+       default:
+               DRM_DEBUG_KMS("VBT has unknown eDP voltage swing value %u\n",
+                             edp_link_params->vswing);
+               break;
        }
 }
 
index 69bcc42a0e44327679217d29a9415e553bd3564b..5b60e25baa321367775e1d75e29a5ad153d72a51 100644 (file)
@@ -7825,14 +7825,12 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
                addr = i915_gem_obj_ggtt_offset(obj);
        } else {
                int align = IS_I830(dev) ? 16 * 1024 : 256;
-               ret = i915_gem_attach_phys_object(dev, obj,
-                                                 (intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1,
-                                                 align);
+               ret = i915_gem_object_attach_phys(obj, align);
                if (ret) {
                        DRM_DEBUG_KMS("failed to attach phys object\n");
                        goto fail_locked;
                }
-               addr = obj->phys_obj->handle->busaddr;
+               addr = obj->phys_handle->busaddr;
        }
 
        if (IS_GEN2(dev))
@@ -7840,10 +7838,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 
  finish:
        if (intel_crtc->cursor_bo) {
-               if (INTEL_INFO(dev)->cursor_needs_physical) {
-                       if (intel_crtc->cursor_bo != obj)
-                               i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
-               } else
+               if (!INTEL_INFO(dev)->cursor_needs_physical)
                        i915_gem_object_unpin_from_display_plane(intel_crtc->cursor_bo);
                drm_gem_object_unreference(&intel_crtc->cursor_bo->base);
        }
@@ -11395,15 +11390,6 @@ void intel_modeset_init(struct drm_device *dev)
        }
 }
 
-static void
-intel_connector_break_all_links(struct intel_connector *connector)
-{
-       connector->base.dpms = DRM_MODE_DPMS_OFF;
-       connector->base.encoder = NULL;
-       connector->encoder->connectors_active = false;
-       connector->encoder->base.crtc = NULL;
-}
-
 static void intel_enable_pipe_a(struct drm_device *dev)
 {
        struct intel_connector *connector;
@@ -11485,8 +11471,17 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
                        if (connector->encoder->base.crtc != &crtc->base)
                                continue;
 
-                       intel_connector_break_all_links(connector);
+                       connector->base.dpms = DRM_MODE_DPMS_OFF;
+                       connector->base.encoder = NULL;
                }
+               /* multiple connectors may have the same encoder:
+                *  handle them and break crtc link separately */
+               list_for_each_entry(connector, &dev->mode_config.connector_list,
+                                   base.head)
+                       if (connector->encoder->base.crtc == &crtc->base) {
+                               connector->encoder->base.crtc = NULL;
+                               connector->encoder->connectors_active = false;
+                       }
 
                WARN_ON(crtc->active);
                crtc->base.enabled = false;
@@ -11568,6 +11563,8 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
                                      drm_get_encoder_name(&encoder->base));
                        encoder->disable(encoder);
                }
+               encoder->base.crtc = NULL;
+               encoder->connectors_active = false;
 
                /* Inconsistent output/port/pipe state happens presumably due to
                 * a bug in one of the get_hw_state functions. Or someplace else
@@ -11578,8 +11575,8 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
                                    base.head) {
                        if (connector->encoder != encoder)
                                continue;
-
-                       intel_connector_break_all_links(connector);
+                       connector->base.dpms = DRM_MODE_DPMS_OFF;
+                       connector->base.encoder = NULL;
                }
        }
        /* Enabled encoders without active connectors will be fixed in
index dfa85289f28f301fe259b522b45ef1521489175e..2a00cb828d20c7549a7b00a6745c228998cc136b 100644 (file)
@@ -105,7 +105,8 @@ intel_dp_max_link_bw(struct intel_dp *intel_dp)
        case DP_LINK_BW_2_7:
                break;
        case DP_LINK_BW_5_4: /* 1.2 capable displays may advertise higher bw */
-               if ((IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) &&
+               if (((IS_HASWELL(dev) && !IS_HSW_ULX(dev)) ||
+                    INTEL_INFO(dev)->gen >= 8) &&
                    intel_dp->dpcd[DP_DPCD_REV] >= 0x12)
                        max_link_bw = DP_LINK_BW_5_4;
                else
@@ -120,6 +121,22 @@ intel_dp_max_link_bw(struct intel_dp *intel_dp)
        return max_link_bw;
 }
 
+static u8 intel_dp_max_lane_count(struct intel_dp *intel_dp)
+{
+       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+       struct drm_device *dev = intel_dig_port->base.base.dev;
+       u8 source_max, sink_max;
+
+       source_max = 4;
+       if (HAS_DDI(dev) && intel_dig_port->port == PORT_A &&
+           (intel_dig_port->saved_port_bits & DDI_A_4_LANES) == 0)
+               source_max = 2;
+
+       sink_max = drm_dp_max_lane_count(intel_dp->dpcd);
+
+       return min(source_max, sink_max);
+}
+
 /*
  * The units on the numbers in the next two are... bizarre.  Examples will
  * make it clearer; this one parallels an example in the eDP spec.
@@ -170,7 +187,7 @@ intel_dp_mode_valid(struct drm_connector *connector,
        }
 
        max_link_clock = drm_dp_bw_code_to_link_rate(intel_dp_max_link_bw(intel_dp));
-       max_lanes = drm_dp_max_lane_count(intel_dp->dpcd);
+       max_lanes = intel_dp_max_lane_count(intel_dp);
 
        max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
        mode_rate = intel_dp_link_required(target_clock, 18);
@@ -750,8 +767,10 @@ intel_dp_compute_config(struct intel_encoder *encoder,
        struct intel_crtc *intel_crtc = encoder->new_crtc;
        struct intel_connector *intel_connector = intel_dp->attached_connector;
        int lane_count, clock;
-       int max_lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
+       int min_lane_count = 1;
+       int max_lane_count = intel_dp_max_lane_count(intel_dp);
        /* Conveniently, the link BW constants become indices with a shift...*/
+       int min_clock = 0;
        int max_clock = intel_dp_max_link_bw(intel_dp) >> 3;
        int bpp, mode_rate;
        static int bws[] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7, DP_LINK_BW_5_4 };
@@ -784,19 +803,38 @@ intel_dp_compute_config(struct intel_encoder *encoder,
        /* Walk through all bpp values. Luckily they're all nicely spaced with 2
         * bpc in between. */
        bpp = pipe_config->pipe_bpp;
-       if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp &&
-           dev_priv->vbt.edp_bpp < bpp) {
-               DRM_DEBUG_KMS("clamping bpp for eDP panel to BIOS-provided %i\n",
-                             dev_priv->vbt.edp_bpp);
-               bpp = dev_priv->vbt.edp_bpp;
+       if (is_edp(intel_dp)) {
+               if (dev_priv->vbt.edp_bpp && dev_priv->vbt.edp_bpp < bpp) {
+                       DRM_DEBUG_KMS("clamping bpp for eDP panel to BIOS-provided %i\n",
+                                     dev_priv->vbt.edp_bpp);
+                       bpp = dev_priv->vbt.edp_bpp;
+               }
+
+               if (IS_BROADWELL(dev)) {
+                       /* Yes, it's an ugly hack. */
+                       min_lane_count = max_lane_count;
+                       DRM_DEBUG_KMS("forcing lane count to max (%u) on BDW\n",
+                                     min_lane_count);
+               } else if (dev_priv->vbt.edp_lanes) {
+                       min_lane_count = min(dev_priv->vbt.edp_lanes,
+                                            max_lane_count);
+                       DRM_DEBUG_KMS("using min %u lanes per VBT\n",
+                                     min_lane_count);
+               }
+
+               if (dev_priv->vbt.edp_rate) {
+                       min_clock = min(dev_priv->vbt.edp_rate >> 3, max_clock);
+                       DRM_DEBUG_KMS("using min %02x link bw per VBT\n",
+                                     bws[min_clock]);
+               }
        }
 
        for (; bpp >= 6*3; bpp -= 2*3) {
                mode_rate = intel_dp_link_required(adjusted_mode->crtc_clock,
                                                   bpp);
 
-               for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
-                       for (clock = 0; clock <= max_clock; clock++) {
+               for (lane_count = min_lane_count; lane_count <= max_lane_count; lane_count <<= 1) {
+                       for (clock = min_clock; clock <= max_clock; clock++) {
                                link_clock = drm_dp_bw_code_to_link_rate(bws[clock]);
                                link_avail = intel_dp_max_data_rate(link_clock,
                                                                    lane_count);
index fce4a0d93c0b19b7d51f4d2578331b13aef51399..f73ba5e6b7a8d685b4530e16c6735c095c2aeb5f 100644 (file)
@@ -387,6 +387,15 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
                                                          height);
                }
 
+               /* No preferred mode marked by the EDID? Are there any modes? */
+               if (!modes[i] && !list_empty(&connector->modes)) {
+                       DRM_DEBUG_KMS("using first mode listed on connector %s\n",
+                                     drm_get_connector_name(connector));
+                       modes[i] = list_first_entry(&connector->modes,
+                                                   struct drm_display_mode,
+                                                   head);
+               }
+
                /* last resort: use current mode */
                if (!modes[i]) {
                        /*
index d8adc9104dca89395ae8016950e0715430354e7d..129db0c7d83579750118172220d0c8380228dd72 100644 (file)
@@ -193,7 +193,7 @@ intel_overlay_map_regs(struct intel_overlay *overlay)
        struct overlay_registers __iomem *regs;
 
        if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
-               regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_obj->handle->vaddr;
+               regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_handle->vaddr;
        else
                regs = io_mapping_map_wc(dev_priv->gtt.mappable,
                                         i915_gem_obj_ggtt_offset(overlay->reg_bo));
@@ -1340,14 +1340,12 @@ void intel_setup_overlay(struct drm_device *dev)
        overlay->reg_bo = reg_bo;
 
        if (OVERLAY_NEEDS_PHYSICAL(dev)) {
-               ret = i915_gem_attach_phys_object(dev, reg_bo,
-                                                 I915_GEM_PHYS_OVERLAY_REGS,
-                                                 PAGE_SIZE);
+               ret = i915_gem_object_attach_phys(reg_bo, PAGE_SIZE);
                if (ret) {
                        DRM_ERROR("failed to attach phys overlay regs\n");
                        goto out_free_bo;
                }
-               overlay->flip_addr = reg_bo->phys_obj->handle->busaddr;
+               overlay->flip_addr = reg_bo->phys_handle->busaddr;
        } else {
                ret = i915_gem_obj_ggtt_pin(reg_bo, PAGE_SIZE, PIN_MAPPABLE);
                if (ret) {
@@ -1428,7 +1426,7 @@ intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
                /* Cast to make sparse happy, but it's wc memory anyway, so
                 * equivalent to the wc io mapping on X86. */
                regs = (struct overlay_registers __iomem *)
-                       overlay->reg_bo->phys_obj->handle->vaddr;
+                       overlay->reg_bo->phys_handle->vaddr;
        else
                regs = io_mapping_map_atomic_wc(dev_priv->gtt.mappable,
                                                i915_gem_obj_ggtt_offset(overlay->reg_bo));
@@ -1462,7 +1460,7 @@ intel_overlay_capture_error_state(struct drm_device *dev)
        error->dovsta = I915_READ(DOVSTA);
        error->isr = I915_READ(ISR);
        if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
-               error->base = (__force long)overlay->reg_bo->phys_obj->handle->vaddr;
+               error->base = (__force long)overlay->reg_bo->phys_handle->vaddr;
        else
                error->base = i915_gem_obj_ggtt_offset(overlay->reg_bo);
 
index 0eead16aeda7404053de8c9885992b0904c1049c..cb8cfb7e09749938383c18a7eb6e2bc149823095 100644 (file)
@@ -492,6 +492,7 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
        enum pipe pipe = intel_get_pipe_from_connector(connector);
        u32 freq;
        unsigned long flags;
+       u64 n;
 
        if (!panel->backlight.present || pipe == INVALID_PIPE)
                return;
@@ -502,10 +503,9 @@ void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
 
        /* scale to hardware max, but be careful to not overflow */
        freq = panel->backlight.max;
-       if (freq < max)
-               level = level * freq / max;
-       else
-               level = freq / max * level;
+       n = (u64)level * freq;
+       do_div(n, max);
+       level = n;
 
        panel->backlight.level = level;
        if (panel->backlight.device)
index 19e94c3edc1957d96b928fb23d696b393216fc42..d93dcf683e8c3695960ca93c92dce87a7823d3f2 100644 (file)
@@ -2095,6 +2095,43 @@ static void intel_print_wm_latency(struct drm_device *dev,
        }
 }
 
+static bool ilk_increase_wm_latency(struct drm_i915_private *dev_priv,
+                                   uint16_t wm[5], uint16_t min)
+{
+       int level, max_level = ilk_wm_max_level(dev_priv->dev);
+
+       if (wm[0] >= min)
+               return false;
+
+       wm[0] = max(wm[0], min);
+       for (level = 1; level <= max_level; level++)
+               wm[level] = max_t(uint16_t, wm[level], DIV_ROUND_UP(min, 5));
+
+       return true;
+}
+
+static void snb_wm_latency_quirk(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       bool changed;
+
+       /*
+        * The BIOS provided WM memory latency values are often
+        * inadequate for high resolution displays. Adjust them.
+        */
+       changed = ilk_increase_wm_latency(dev_priv, dev_priv->wm.pri_latency, 12) |
+               ilk_increase_wm_latency(dev_priv, dev_priv->wm.spr_latency, 12) |
+               ilk_increase_wm_latency(dev_priv, dev_priv->wm.cur_latency, 12);
+
+       if (!changed)
+               return;
+
+       DRM_DEBUG_KMS("WM latency values increased to avoid potential underruns\n");
+       intel_print_wm_latency(dev, "Primary", dev_priv->wm.pri_latency);
+       intel_print_wm_latency(dev, "Sprite", dev_priv->wm.spr_latency);
+       intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency);
+}
+
 static void ilk_setup_wm_latency(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2112,6 +2149,9 @@ static void ilk_setup_wm_latency(struct drm_device *dev)
        intel_print_wm_latency(dev, "Primary", dev_priv->wm.pri_latency);
        intel_print_wm_latency(dev, "Sprite", dev_priv->wm.spr_latency);
        intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency);
+
+       if (IS_GEN6(dev))
+               snb_wm_latency_quirk(dev);
 }
 
 static void ilk_compute_wm_parameters(struct drm_crtc *crtc,
index d27155adf5db2b039dee51b9aa0de25e60c8967e..46be00d66df3da3e74597ba9c02f0ac745741751 100644 (file)
@@ -2424,8 +2424,8 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
        if (ret < 0)
                goto err1;
 
-       ret = sysfs_create_link(&encoder->ddc.dev.kobj,
-                               &drm_connector->kdev->kobj,
+       ret = sysfs_create_link(&drm_connector->kdev->kobj,
+                               &encoder->ddc.dev.kobj,
                                encoder->ddc.dev.kobj.name);
        if (ret < 0)
                goto err2;
index f729dc71d5beb031599aca72f82c90ec946e2fe0..d0c75779d3f6f91e9cc98b0f1a853344783fdb48 100644 (file)
@@ -185,6 +185,8 @@ static void vlv_force_wake_reset(struct drm_i915_private *dev_priv)
 {
        __raw_i915_write32(dev_priv, FORCEWAKE_VLV,
                           _MASKED_BIT_DISABLE(0xffff));
+       __raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
+                          _MASKED_BIT_DISABLE(0xffff));
        /* something from same cacheline, but !FORCEWAKE_VLV */
        __raw_posting_read(dev_priv, FORCEWAKE_ACK_VLV);
 }
index 7762665ad8fdb5b461680ee84b7b224b77a5d4d5..876de9ac3793fd30af193ac7e8410818bdb56e7a 100644 (file)
@@ -1009,7 +1009,7 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id,
        }
 
        if (outp == 8)
-               return false;
+               return conf;
 
        data = exec_lookup(priv, head, outp, ctrl, dcb, &ver, &hdr, &cnt, &len, &info1);
        if (data == 0x0000)
index 1dc37b1ddbfac0a2ecddcfdcd59a80a267e65520..b0d0fb2f4d083813a799d1c02bb3d953646f2889 100644 (file)
@@ -863,7 +863,7 @@ gm107_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
 {
        mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
        mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS);
-       mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
+       mmio_data(0x200000, 0x1000, NV_MEM_ACCESS_RW);
 
        mmio_list(0x40800c, 0x00000000,  8, 1);
        mmio_list(0x408010, 0x80000000,  0, 0);
@@ -877,6 +877,8 @@ gm107_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
        mmio_list(0x418e24, 0x00000000,  8, 0);
        mmio_list(0x418e28, 0x80000030,  0, 0);
 
+       mmio_list(0x4064c8, 0x018002c0,  0, 0);
+
        mmio_list(0x418810, 0x80000000, 12, 2);
        mmio_list(0x419848, 0x10000000, 12, 2);
        mmio_list(0x419c2c, 0x10000000, 12, 2);
index fb0b6b2d1427f436f14666c3611d4d6807bd2d36..222e8ebb669dff496534331682e7a77c7e6bd9e0 100644 (file)
@@ -168,7 +168,8 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
         */
        i = 16;
        do {
-               if ((nv_rd32(bios, 0x300000) & 0xffff) == 0xaa55)
+               u32 data = le32_to_cpu(nv_rd32(bios, 0x300000)) & 0xffff;
+               if (data == 0xaa55)
                        break;
        } while (i--);
 
@@ -176,14 +177,15 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
                goto out;
 
        /* read entire bios image to system memory */
-       bios->size = ((nv_rd32(bios, 0x300000) >> 16) & 0xff) * 512;
+       bios->size = (le32_to_cpu(nv_rd32(bios, 0x300000)) >> 16) & 0xff;
+       bios->size = bios->size * 512;
        if (!bios->size)
                goto out;
 
        bios->data = kmalloc(bios->size, GFP_KERNEL);
        if (bios->data) {
-               for (i = 0; i < bios->size; i+=4)
-                       nv_wo32(bios, i, nv_rd32(bios, 0x300000 + i));
+               for (i = 0; i < bios->size; i += 4)
+                       ((u32 *)bios->data)[i/4] = nv_rd32(bios, 0x300000 + i);
        }
 
        /* check the PCI record header */
index 43fec17ea540b6c53af704931d4baf29d2391e4e..bbf117be572f4617cff0fd06907fb2a13977ae93 100644 (file)
@@ -40,6 +40,7 @@ pwm_info(struct nouveau_therm *therm, int line)
                case 0x00: return 2;
                case 0x19: return 1;
                case 0x1c: return 0;
+               case 0x1e: return 2;
                default:
                        break;
                }
index 83face3f608f020f70d7d11dda363c5817102238..279206997e5cd7d091d44e26f84ce5efdfb06f1d 100644 (file)
@@ -389,9 +389,6 @@ bool nouveau_acpi_rom_supported(struct pci_dev *pdev)
        acpi_status status;
        acpi_handle dhandle, rom_handle;
 
-       if (!nouveau_dsm_priv.dsm_detected && !nouveau_dsm_priv.optimus_detected)
-               return false;
-
        dhandle = ACPI_HANDLE(&pdev->dev);
        if (!dhandle)
                return false;
index 3ff030dc1ee35d34925b2fd5464f1236ad10d925..da764a4ed9588273fe6cf02ed0d6c589aa2ebda0 100644 (file)
@@ -764,9 +764,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        }
 
        ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
-       mutex_unlock(&chan->cli->mutex);
        if (ret)
                goto fail_unreserve;
+       mutex_unlock(&chan->cli->mutex);
 
        /* Update the crtc struct and cleanup */
        crtc->primary->fb = fb;
index fb187c78978f8d5a139359381870aaea8ad1cc91..c31c12b4e66681614f0d294e4fd0a0cf19350c88 100644 (file)
@@ -1177,27 +1177,43 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
 
                /* Set NUM_BANKS. */
                if (rdev->family >= CHIP_TAHITI) {
-                       unsigned tileb, index, num_banks, tile_split_bytes;
+                       unsigned index, num_banks;
 
-                       /* Calculate the macrotile mode index. */
-                       tile_split_bytes = 64 << tile_split;
-                       tileb = 8 * 8 * target_fb->bits_per_pixel / 8;
-                       tileb = min(tile_split_bytes, tileb);
+                       if (rdev->family >= CHIP_BONAIRE) {
+                               unsigned tileb, tile_split_bytes;
 
-                       for (index = 0; tileb > 64; index++) {
-                               tileb >>= 1;
-                       }
+                               /* Calculate the macrotile mode index. */
+                               tile_split_bytes = 64 << tile_split;
+                               tileb = 8 * 8 * target_fb->bits_per_pixel / 8;
+                               tileb = min(tile_split_bytes, tileb);
 
-                       if (index >= 16) {
-                               DRM_ERROR("Wrong screen bpp (%u) or tile split (%u)\n",
-                                         target_fb->bits_per_pixel, tile_split);
-                               return -EINVAL;
-                       }
+                               for (index = 0; tileb > 64; index++)
+                                       tileb >>= 1;
+
+                               if (index >= 16) {
+                                       DRM_ERROR("Wrong screen bpp (%u) or tile split (%u)\n",
+                                                 target_fb->bits_per_pixel, tile_split);
+                                       return -EINVAL;
+                               }
 
-                       if (rdev->family >= CHIP_BONAIRE)
                                num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3;
-                       else
+                       } else {
+                               switch (target_fb->bits_per_pixel) {
+                               case 8:
+                                       index = 10;
+                                       break;
+                               case 16:
+                                       index = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP;
+                                       break;
+                               default:
+                               case 32:
+                                       index = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP;
+                                       break;
+                               }
+
                                num_banks = (rdev->config.si.tile_mode_array[index] >> 20) & 0x3;
+                       }
+
                        fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks);
                } else {
                        /* NI and older. */
@@ -1720,8 +1736,9 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
                }
                /* otherwise, pick one of the plls */
                if ((rdev->family == CHIP_KAVERI) ||
-                   (rdev->family == CHIP_KABINI)) {
-                       /* KB/KV has PPLL1 and PPLL2 */
+                   (rdev->family == CHIP_KABINI) ||
+                   (rdev->family == CHIP_MULLINS)) {
+                       /* KB/KV/ML has PPLL1 and PPLL2 */
                        pll_in_use = radeon_get_pll_use_mask(crtc);
                        if (!(pll_in_use & (1 << ATOM_PPLL2)))
                                return ATOM_PPLL2;
@@ -1885,6 +1902,9 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
            (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
                is_tvcv = true;
 
+       if (!radeon_crtc->adjusted_clock)
+               return -EINVAL;
+
        atombios_crtc_set_pll(crtc, adjusted_mode);
 
        if (ASIC_IS_DCE4(rdev))
index bc0119fb6c12a9373e1bd282886d38f8ed858135..54e4f52549af47f19edf39340754a4e33a4da49c 100644 (file)
@@ -366,11 +366,11 @@ static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector)
        if (!(dig_connector->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT))
                return;
 
-       if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_SINK_OUI, buf, 3))
+       if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_SINK_OUI, buf, 3) == 3)
                DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n",
                              buf[0], buf[1], buf[2]);
 
-       if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_BRANCH_OUI, buf, 3))
+       if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_BRANCH_OUI, buf, 3) == 3)
                DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
                              buf[0], buf[1], buf[2]);
 }
@@ -419,21 +419,23 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
 
        if (dp_bridge != ENCODER_OBJECT_ID_NONE) {
                /* DP bridge chips */
-               drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux,
-                                 DP_EDP_CONFIGURATION_CAP, &tmp);
-               if (tmp & 1)
-                       panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
-               else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) ||
-                        (dp_bridge == ENCODER_OBJECT_ID_TRAVIS))
-                       panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
-               else
-                       panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
+               if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux,
+                                     DP_EDP_CONFIGURATION_CAP, &tmp) == 1) {
+                       if (tmp & 1)
+                               panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
+                       else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) ||
+                                (dp_bridge == ENCODER_OBJECT_ID_TRAVIS))
+                               panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
+                       else
+                               panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
+               }
        } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
                /* eDP */
-               drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux,
-                                 DP_EDP_CONFIGURATION_CAP, &tmp);
-               if (tmp & 1)
-                       panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
+               if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux,
+                                     DP_EDP_CONFIGURATION_CAP, &tmp) == 1) {
+                       if (tmp & 1)
+                               panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
+               }
        }
 
        return panel_mode;
@@ -809,11 +811,15 @@ void radeon_dp_link_train(struct drm_encoder *encoder,
        else
                dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A;
 
-       drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_MAX_LANE_COUNT, &tmp);
-       if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED))
-               dp_info.tp3_supported = true;
-       else
+       if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_MAX_LANE_COUNT, &tmp)
+           == 1) {
+               if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED))
+                       dp_info.tp3_supported = true;
+               else
+                       dp_info.tp3_supported = false;
+       } else {
                dp_info.tp3_supported = false;
+       }
 
        memcpy(dp_info.dpcd, dig_connector->dpcd, DP_RECEIVER_CAP_SIZE);
        dp_info.rdev = rdev;
index 199eb194716f83b64aa7c3850d30606f4ba3f053..d2fd989680857d5a08a7d65d586bb0b4a40be6e2 100644 (file)
@@ -63,6 +63,12 @@ MODULE_FIRMWARE("radeon/KABINI_ce.bin");
 MODULE_FIRMWARE("radeon/KABINI_mec.bin");
 MODULE_FIRMWARE("radeon/KABINI_rlc.bin");
 MODULE_FIRMWARE("radeon/KABINI_sdma.bin");
+MODULE_FIRMWARE("radeon/MULLINS_pfp.bin");
+MODULE_FIRMWARE("radeon/MULLINS_me.bin");
+MODULE_FIRMWARE("radeon/MULLINS_ce.bin");
+MODULE_FIRMWARE("radeon/MULLINS_mec.bin");
+MODULE_FIRMWARE("radeon/MULLINS_rlc.bin");
+MODULE_FIRMWARE("radeon/MULLINS_sdma.bin");
 
 extern int r600_ih_ring_alloc(struct radeon_device *rdev);
 extern void r600_ih_ring_fini(struct radeon_device *rdev);
@@ -1473,6 +1479,43 @@ static const u32 hawaii_mgcg_cgcg_init[] =
        0xd80c, 0xff000ff0, 0x00000100
 };
 
+static const u32 godavari_golden_registers[] =
+{
+       0x55e4, 0xff607fff, 0xfc000100,
+       0x6ed8, 0x00010101, 0x00010000,
+       0x9830, 0xffffffff, 0x00000000,
+       0x98302, 0xf00fffff, 0x00000400,
+       0x6130, 0xffffffff, 0x00010000,
+       0x5bb0, 0x000000f0, 0x00000070,
+       0x5bc0, 0xf0311fff, 0x80300000,
+       0x98f8, 0x73773777, 0x12010001,
+       0x98fc, 0xffffffff, 0x00000010,
+       0x8030, 0x00001f0f, 0x0000100a,
+       0x2f48, 0x73773777, 0x12010001,
+       0x2408, 0x000fffff, 0x000c007f,
+       0x8a14, 0xf000003f, 0x00000007,
+       0x8b24, 0xffffffff, 0x00ff0fff,
+       0x30a04, 0x0000ff0f, 0x00000000,
+       0x28a4c, 0x07ffffff, 0x06000000,
+       0x4d8, 0x00000fff, 0x00000100,
+       0xd014, 0x00010000, 0x00810001,
+       0xd814, 0x00010000, 0x00810001,
+       0x3e78, 0x00000001, 0x00000002,
+       0xc768, 0x00000008, 0x00000008,
+       0xc770, 0x00000f00, 0x00000800,
+       0xc774, 0x00000f00, 0x00000800,
+       0xc798, 0x00ffffff, 0x00ff7fbf,
+       0xc79c, 0x00ffffff, 0x00ff7faf,
+       0x8c00, 0x000000ff, 0x00000001,
+       0x214f8, 0x01ff01ff, 0x00000002,
+       0x21498, 0x007ff800, 0x00200000,
+       0x2015c, 0xffffffff, 0x00000f40,
+       0x88c4, 0x001f3ae3, 0x00000082,
+       0x88d4, 0x0000001f, 0x00000010,
+       0x30934, 0xffffffff, 0x00000000
+};
+
+
 static void cik_init_golden_registers(struct radeon_device *rdev)
 {
        switch (rdev->family) {
@@ -1504,6 +1547,20 @@ static void cik_init_golden_registers(struct radeon_device *rdev)
                                                 kalindi_golden_spm_registers,
                                                 (const u32)ARRAY_SIZE(kalindi_golden_spm_registers));
                break;
+       case CHIP_MULLINS:
+               radeon_program_register_sequence(rdev,
+                                                kalindi_mgcg_cgcg_init,
+                                                (const u32)ARRAY_SIZE(kalindi_mgcg_cgcg_init));
+               radeon_program_register_sequence(rdev,
+                                                godavari_golden_registers,
+                                                (const u32)ARRAY_SIZE(godavari_golden_registers));
+               radeon_program_register_sequence(rdev,
+                                                kalindi_golden_common_registers,
+                                                (const u32)ARRAY_SIZE(kalindi_golden_common_registers));
+               radeon_program_register_sequence(rdev,
+                                                kalindi_golden_spm_registers,
+                                                (const u32)ARRAY_SIZE(kalindi_golden_spm_registers));
+               break;
        case CHIP_KAVERI:
                radeon_program_register_sequence(rdev,
                                                 spectre_mgcg_cgcg_init,
@@ -1834,6 +1891,15 @@ static int cik_init_microcode(struct radeon_device *rdev)
                rlc_req_size = KB_RLC_UCODE_SIZE * 4;
                sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
                break;
+       case CHIP_MULLINS:
+               chip_name = "MULLINS";
+               pfp_req_size = CIK_PFP_UCODE_SIZE * 4;
+               me_req_size = CIK_ME_UCODE_SIZE * 4;
+               ce_req_size = CIK_CE_UCODE_SIZE * 4;
+               mec_req_size = CIK_MEC_UCODE_SIZE * 4;
+               rlc_req_size = ML_RLC_UCODE_SIZE * 4;
+               sdma_req_size = CIK_SDMA_UCODE_SIZE * 4;
+               break;
        default: BUG();
        }
 
@@ -3272,6 +3338,7 @@ static void cik_gpu_init(struct radeon_device *rdev)
                gb_addr_config = BONAIRE_GB_ADDR_CONFIG_GOLDEN;
                break;
        case CHIP_KABINI:
+       case CHIP_MULLINS:
        default:
                rdev->config.cik.max_shader_engines = 1;
                rdev->config.cik.max_tile_pipes = 2;
@@ -3702,6 +3769,7 @@ int cik_copy_cpdma(struct radeon_device *rdev,
        r = radeon_fence_emit(rdev, fence, ring->idx);
        if (r) {
                radeon_ring_unlock_undo(rdev, ring);
+               radeon_semaphore_free(rdev, &sem, NULL);
                return r;
        }
 
@@ -5800,6 +5868,9 @@ static int cik_rlc_resume(struct radeon_device *rdev)
        case CHIP_KABINI:
                size = KB_RLC_UCODE_SIZE;
                break;
+       case CHIP_MULLINS:
+               size = ML_RLC_UCODE_SIZE;
+               break;
        }
 
        cik_rlc_stop(rdev);
@@ -6548,6 +6619,7 @@ void cik_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer)
                buffer[count++] = cpu_to_le32(0x00000000);
                break;
        case CHIP_KABINI:
+       case CHIP_MULLINS:
                buffer[count++] = cpu_to_le32(0x00000000); /* XXX */
                buffer[count++] = cpu_to_le32(0x00000000);
                break;
@@ -6693,6 +6765,19 @@ static void cik_disable_interrupt_state(struct radeon_device *rdev)
                WREG32(LB_INTERRUPT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
                WREG32(LB_INTERRUPT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
        }
+       /* pflip */
+       if (rdev->num_crtc >= 2) {
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
+       }
+       if (rdev->num_crtc >= 4) {
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
+       }
+       if (rdev->num_crtc >= 6) {
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+       }
 
        /* dac hotplug */
        WREG32(DAC_AUTODETECT_INT_CONTROL, 0);
@@ -7049,6 +7134,25 @@ int cik_irq_set(struct radeon_device *rdev)
                WREG32(LB_INTERRUPT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
        }
 
+       if (rdev->num_crtc >= 2) {
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
+                      GRPH_PFLIP_INT_MASK);
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
+                      GRPH_PFLIP_INT_MASK);
+       }
+       if (rdev->num_crtc >= 4) {
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
+                      GRPH_PFLIP_INT_MASK);
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
+                      GRPH_PFLIP_INT_MASK);
+       }
+       if (rdev->num_crtc >= 6) {
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
+                      GRPH_PFLIP_INT_MASK);
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
+                      GRPH_PFLIP_INT_MASK);
+       }
+
        WREG32(DC_HPD1_INT_CONTROL, hpd1);
        WREG32(DC_HPD2_INT_CONTROL, hpd2);
        WREG32(DC_HPD3_INT_CONTROL, hpd3);
@@ -7085,6 +7189,29 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
        rdev->irq.stat_regs.cik.disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5);
        rdev->irq.stat_regs.cik.disp_int_cont6 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE6);
 
+       rdev->irq.stat_regs.cik.d1grph_int = RREG32(GRPH_INT_STATUS +
+               EVERGREEN_CRTC0_REGISTER_OFFSET);
+       rdev->irq.stat_regs.cik.d2grph_int = RREG32(GRPH_INT_STATUS +
+               EVERGREEN_CRTC1_REGISTER_OFFSET);
+       if (rdev->num_crtc >= 4) {
+               rdev->irq.stat_regs.cik.d3grph_int = RREG32(GRPH_INT_STATUS +
+                       EVERGREEN_CRTC2_REGISTER_OFFSET);
+               rdev->irq.stat_regs.cik.d4grph_int = RREG32(GRPH_INT_STATUS +
+                       EVERGREEN_CRTC3_REGISTER_OFFSET);
+       }
+       if (rdev->num_crtc >= 6) {
+               rdev->irq.stat_regs.cik.d5grph_int = RREG32(GRPH_INT_STATUS +
+                       EVERGREEN_CRTC4_REGISTER_OFFSET);
+               rdev->irq.stat_regs.cik.d6grph_int = RREG32(GRPH_INT_STATUS +
+                       EVERGREEN_CRTC5_REGISTER_OFFSET);
+       }
+
+       if (rdev->irq.stat_regs.cik.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
+               WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET,
+                      GRPH_PFLIP_INT_CLEAR);
+       if (rdev->irq.stat_regs.cik.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
+               WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET,
+                      GRPH_PFLIP_INT_CLEAR);
        if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VBLANK_INTERRUPT)
                WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
        if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VLINE_INTERRUPT)
@@ -7095,6 +7222,12 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
                WREG32(LB_VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);
 
        if (rdev->num_crtc >= 4) {
+               if (rdev->irq.stat_regs.cik.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
+                       WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET,
+                              GRPH_PFLIP_INT_CLEAR);
+               if (rdev->irq.stat_regs.cik.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
+                       WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET,
+                              GRPH_PFLIP_INT_CLEAR);
                if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
                        WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
                if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
@@ -7106,6 +7239,12 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
        }
 
        if (rdev->num_crtc >= 6) {
+               if (rdev->irq.stat_regs.cik.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
+                       WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET,
+                              GRPH_PFLIP_INT_CLEAR);
+               if (rdev->irq.stat_regs.cik.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
+                       WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET,
+                              GRPH_PFLIP_INT_CLEAR);
                if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
                        WREG32(LB_VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
                if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
@@ -7457,6 +7596,15 @@ restart_ih:
                                break;
                        }
                        break;
+               case 8: /* D1 page flip */
+               case 10: /* D2 page flip */
+               case 12: /* D3 page flip */
+               case 14: /* D4 page flip */
+               case 16: /* D5 page flip */
+               case 18: /* D6 page flip */
+                       DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1);
+                       radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
+                       break;
                case 42: /* HPD hotplug */
                        switch (src_data) {
                        case 0:
index f7e46cf682afdcbe051cb4a6ecf6dfe66570a5c3..72e464c79a88a777c27d2ada64667bf9e8798aa2 100644 (file)
@@ -562,6 +562,7 @@ int cik_copy_dma(struct radeon_device *rdev,
        r = radeon_fence_emit(rdev, fence, ring->idx);
        if (r) {
                radeon_ring_unlock_undo(rdev, ring);
+               radeon_semaphore_free(rdev, &sem, NULL);
                return r;
        }
 
index 213873270d5f6b705974aa57867f0dff47b7901a..dd7926394a8fdaf6821fdd10151f98639c7c082f 100644 (file)
 #       define DC_HPD6_RX_INTERRUPT                     (1 << 18)
 #define DISP_INTERRUPT_STATUS_CONTINUE6                 0x6780
 
+/* 0x6858, 0x7458, 0x10058, 0x10c58, 0x11858, 0x12458 */
+#define GRPH_INT_STATUS                                 0x6858
+#       define GRPH_PFLIP_INT_OCCURRED                  (1 << 0)
+#       define GRPH_PFLIP_INT_CLEAR                     (1 << 8)
+/* 0x685c, 0x745c, 0x1005c, 0x10c5c, 0x1185c, 0x1245c */
+#define GRPH_INT_CONTROL                                0x685c
+#       define GRPH_PFLIP_INT_MASK                      (1 << 0)
+#       define GRPH_PFLIP_INT_TYPE                      (1 << 8)
+
 #define        DAC_AUTODETECT_INT_CONTROL                      0x67c8
 
 #define DC_HPD1_INT_STATUS                              0x601c
index b406546440da7cda8d7da10f7acbf6e6c22186e0..0f7a51a3694f0fff5bde09c7a4bf57dd7bd51963 100644 (file)
@@ -4371,7 +4371,6 @@ int evergreen_irq_set(struct radeon_device *rdev)
        u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0;
        u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6;
        u32 grbm_int_cntl = 0;
-       u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0;
        u32 afmt1 = 0, afmt2 = 0, afmt3 = 0, afmt4 = 0, afmt5 = 0, afmt6 = 0;
        u32 dma_cntl, dma_cntl1 = 0;
        u32 thermal_int = 0;
@@ -4554,15 +4553,21 @@ int evergreen_irq_set(struct radeon_device *rdev)
                WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
        }
 
-       WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1);
-       WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2);
+       WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
+              GRPH_PFLIP_INT_MASK);
+       WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
+              GRPH_PFLIP_INT_MASK);
        if (rdev->num_crtc >= 4) {
-               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3);
-               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4);
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
+                      GRPH_PFLIP_INT_MASK);
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
+                      GRPH_PFLIP_INT_MASK);
        }
        if (rdev->num_crtc >= 6) {
-               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5);
-               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6);
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
+                      GRPH_PFLIP_INT_MASK);
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
+                      GRPH_PFLIP_INT_MASK);
        }
 
        WREG32(DC_HPD1_INT_CONTROL, hpd1);
@@ -4951,6 +4956,15 @@ restart_ih:
                                break;
                        }
                        break;
+               case 8: /* D1 page flip */
+               case 10: /* D2 page flip */
+               case 12: /* D3 page flip */
+               case 14: /* D4 page flip */
+               case 16: /* D5 page flip */
+               case 18: /* D6 page flip */
+                       DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1);
+                       radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
+                       break;
                case 42: /* HPD hotplug */
                        switch (src_data) {
                        case 0:
index 287fe966d7de135161704b0e80ec38676ae1424b..478caefe0fef918011fadd78e1419ac92183ae54 100644 (file)
@@ -151,6 +151,7 @@ int evergreen_copy_dma(struct radeon_device *rdev,
        r = radeon_fence_emit(rdev, fence, ring->idx);
        if (r) {
                radeon_ring_unlock_undo(rdev, ring);
+               radeon_semaphore_free(rdev, &sem, NULL);
                return r;
        }
 
index 16ec9d56a234b107742a13acd5a9684f62aabf42..3f6e817d97ee80cb0013c85818a1ec0c4c110e79 100644 (file)
@@ -546,6 +546,52 @@ static int kv_set_divider_value(struct radeon_device *rdev,
        return 0;
 }
 
+static u32 kv_convert_vid2_to_vid7(struct radeon_device *rdev,
+                                  struct sumo_vid_mapping_table *vid_mapping_table,
+                                  u32 vid_2bit)
+{
+       struct radeon_clock_voltage_dependency_table *vddc_sclk_table =
+               &rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk;
+       u32 i;
+
+       if (vddc_sclk_table && vddc_sclk_table->count) {
+               if (vid_2bit < vddc_sclk_table->count)
+                       return vddc_sclk_table->entries[vid_2bit].v;
+               else
+                       return vddc_sclk_table->entries[vddc_sclk_table->count - 1].v;
+       } else {
+               for (i = 0; i < vid_mapping_table->num_entries; i++) {
+                       if (vid_mapping_table->entries[i].vid_2bit == vid_2bit)
+                               return vid_mapping_table->entries[i].vid_7bit;
+               }
+               return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_7bit;
+       }
+}
+
+static u32 kv_convert_vid7_to_vid2(struct radeon_device *rdev,
+                                  struct sumo_vid_mapping_table *vid_mapping_table,
+                                  u32 vid_7bit)
+{
+       struct radeon_clock_voltage_dependency_table *vddc_sclk_table =
+               &rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk;
+       u32 i;
+
+       if (vddc_sclk_table && vddc_sclk_table->count) {
+               for (i = 0; i < vddc_sclk_table->count; i++) {
+                       if (vddc_sclk_table->entries[i].v == vid_7bit)
+                               return i;
+               }
+               return vddc_sclk_table->count - 1;
+       } else {
+               for (i = 0; i < vid_mapping_table->num_entries; i++) {
+                       if (vid_mapping_table->entries[i].vid_7bit == vid_7bit)
+                               return vid_mapping_table->entries[i].vid_2bit;
+               }
+
+               return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_2bit;
+       }
+}
+
 static u16 kv_convert_8bit_index_to_voltage(struct radeon_device *rdev,
                                            u16 voltage)
 {
@@ -556,9 +602,9 @@ static u16 kv_convert_2bit_index_to_voltage(struct radeon_device *rdev,
                                            u32 vid_2bit)
 {
        struct kv_power_info *pi = kv_get_pi(rdev);
-       u32 vid_8bit = sumo_convert_vid2_to_vid7(rdev,
-                                                &pi->sys_info.vid_mapping_table,
-                                                vid_2bit);
+       u32 vid_8bit = kv_convert_vid2_to_vid7(rdev,
+                                              &pi->sys_info.vid_mapping_table,
+                                              vid_2bit);
 
        return kv_convert_8bit_index_to_voltage(rdev, (u16)vid_8bit);
 }
@@ -639,7 +685,7 @@ static int kv_force_lowest_valid(struct radeon_device *rdev)
 
 static int kv_unforce_levels(struct radeon_device *rdev)
 {
-       if (rdev->family == CHIP_KABINI)
+       if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS)
                return kv_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel);
        else
                return kv_set_enabled_levels(rdev);
@@ -1362,13 +1408,20 @@ static int kv_update_uvd_dpm(struct radeon_device *rdev, bool gate)
        struct radeon_uvd_clock_voltage_dependency_table *table =
                &rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table;
        int ret;
+       u32 mask;
 
        if (!gate) {
-               if (!pi->caps_uvd_dpm || table->count || pi->caps_stable_p_state)
+               if (table->count)
                        pi->uvd_boot_level = table->count - 1;
                else
                        pi->uvd_boot_level = 0;
 
+               if (!pi->caps_uvd_dpm || pi->caps_stable_p_state) {
+                       mask = 1 << pi->uvd_boot_level;
+               } else {
+                       mask = 0x1f;
+               }
+
                ret = kv_copy_bytes_to_smc(rdev,
                                           pi->dpm_table_start +
                                           offsetof(SMU7_Fusion_DpmTable, UvdBootLevel),
@@ -1377,11 +1430,9 @@ static int kv_update_uvd_dpm(struct radeon_device *rdev, bool gate)
                if (ret)
                        return ret;
 
-               if (!pi->caps_uvd_dpm ||
-                   pi->caps_stable_p_state)
-                       kv_send_msg_to_smc_with_parameter(rdev,
-                                                         PPSMC_MSG_UVDDPM_SetEnabledMask,
-                                                         (1 << pi->uvd_boot_level));
+               kv_send_msg_to_smc_with_parameter(rdev,
+                                                 PPSMC_MSG_UVDDPM_SetEnabledMask,
+                                                 mask);
        }
 
        return kv_enable_uvd_dpm(rdev, !gate);
@@ -1617,7 +1668,7 @@ static void kv_dpm_powergate_acp(struct radeon_device *rdev, bool gate)
        if (pi->acp_power_gated == gate)
                return;
 
-       if (rdev->family == CHIP_KABINI)
+       if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS)
                return;
 
        pi->acp_power_gated = gate;
@@ -1786,7 +1837,7 @@ int kv_dpm_set_power_state(struct radeon_device *rdev)
                }
        }
 
-       if (rdev->family == CHIP_KABINI) {
+       if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) {
                if (pi->enable_dpm) {
                        kv_set_valid_clock_range(rdev, new_ps);
                        kv_update_dfs_bypass_settings(rdev, new_ps);
@@ -1812,6 +1863,8 @@ int kv_dpm_set_power_state(struct radeon_device *rdev)
                                return ret;
                        }
                        kv_update_sclk_t(rdev);
+                       if (rdev->family == CHIP_MULLINS)
+                               kv_enable_nb_dpm(rdev);
                }
        } else {
                if (pi->enable_dpm) {
@@ -1862,7 +1915,7 @@ void kv_dpm_reset_asic(struct radeon_device *rdev)
 {
        struct kv_power_info *pi = kv_get_pi(rdev);
 
-       if (rdev->family == CHIP_KABINI) {
+       if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) {
                kv_force_lowest_valid(rdev);
                kv_init_graphics_levels(rdev);
                kv_program_bootup_state(rdev);
@@ -1901,14 +1954,41 @@ static void kv_construct_max_power_limits_table(struct radeon_device *rdev,
 static void kv_patch_voltage_values(struct radeon_device *rdev)
 {
        int i;
-       struct radeon_uvd_clock_voltage_dependency_table *table =
+       struct radeon_uvd_clock_voltage_dependency_table *uvd_table =
                &rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table;
+       struct radeon_vce_clock_voltage_dependency_table *vce_table =
+               &rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
+       struct radeon_clock_voltage_dependency_table *samu_table =
+               &rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table;
+       struct radeon_clock_voltage_dependency_table *acp_table =
+               &rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table;
 
-       if (table->count) {
-               for (i = 0; i < table->count; i++)
-                       table->entries[i].v =
+       if (uvd_table->count) {
+               for (i = 0; i < uvd_table->count; i++)
+                       uvd_table->entries[i].v =
                                kv_convert_8bit_index_to_voltage(rdev,
-                                                                table->entries[i].v);
+                                                                uvd_table->entries[i].v);
+       }
+
+       if (vce_table->count) {
+               for (i = 0; i < vce_table->count; i++)
+                       vce_table->entries[i].v =
+                               kv_convert_8bit_index_to_voltage(rdev,
+                                                                vce_table->entries[i].v);
+       }
+
+       if (samu_table->count) {
+               for (i = 0; i < samu_table->count; i++)
+                       samu_table->entries[i].v =
+                               kv_convert_8bit_index_to_voltage(rdev,
+                                                                samu_table->entries[i].v);
+       }
+
+       if (acp_table->count) {
+               for (i = 0; i < acp_table->count; i++)
+                       acp_table->entries[i].v =
+                               kv_convert_8bit_index_to_voltage(rdev,
+                                                                acp_table->entries[i].v);
        }
 
 }
@@ -1941,7 +2021,7 @@ static int kv_force_dpm_highest(struct radeon_device *rdev)
                        break;
        }
 
-       if (rdev->family == CHIP_KABINI)
+       if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS)
                return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i);
        else
                return kv_set_enabled_level(rdev, i);
@@ -1961,7 +2041,7 @@ static int kv_force_dpm_lowest(struct radeon_device *rdev)
                        break;
        }
 
-       if (rdev->family == CHIP_KABINI)
+       if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS)
                return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i);
        else
                return kv_set_enabled_level(rdev, i);
@@ -2118,7 +2198,7 @@ static void kv_apply_state_adjust_rules(struct radeon_device *rdev,
        else
                pi->battery_state = false;
 
-       if (rdev->family == CHIP_KABINI) {
+       if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) {
                ps->dpm0_pg_nb_ps_lo = 0x1;
                ps->dpm0_pg_nb_ps_hi = 0x0;
                ps->dpmx_nb_ps_lo = 0x1;
@@ -2179,7 +2259,7 @@ static int kv_calculate_nbps_level_settings(struct radeon_device *rdev)
        if (pi->lowest_valid > pi->highest_valid)
                return -EINVAL;
 
-       if (rdev->family == CHIP_KABINI) {
+       if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) {
                for (i = pi->lowest_valid; i <= pi->highest_valid; i++) {
                        pi->graphics_level[i].GnbSlow = 1;
                        pi->graphics_level[i].ForceNbPs1 = 0;
@@ -2253,9 +2333,9 @@ static void kv_init_graphics_levels(struct radeon_device *rdev)
                                break;
 
                        kv_set_divider_value(rdev, i, table->entries[i].clk);
-                       vid_2bit = sumo_convert_vid7_to_vid2(rdev,
-                                                            &pi->sys_info.vid_mapping_table,
-                                                            table->entries[i].v);
+                       vid_2bit = kv_convert_vid7_to_vid2(rdev,
+                                                          &pi->sys_info.vid_mapping_table,
+                                                          table->entries[i].v);
                        kv_set_vid(rdev, i, vid_2bit);
                        kv_set_at(rdev, i, pi->at[i]);
                        kv_dpm_power_level_enabled_for_throttle(rdev, i, true);
@@ -2324,7 +2404,7 @@ static void kv_program_nbps_index_settings(struct radeon_device *rdev,
        struct kv_power_info *pi = kv_get_pi(rdev);
        u32 nbdpmconfig1;
 
-       if (rdev->family == CHIP_KABINI)
+       if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS)
                return;
 
        if (pi->sys_info.nb_dpm_enable) {
@@ -2631,9 +2711,6 @@ int kv_dpm_init(struct radeon_device *rdev)
 
         pi->sram_end = SMC_RAM_END;
 
-       if (rdev->family == CHIP_KABINI)
-               pi->high_voltage_t = 4001;
-
        pi->enable_nb_dpm = true;
 
        pi->caps_power_containment = true;
index 6e887d004ebad7041e2080af850cc6ac2a12367d..bbc189fd3ddc47f57993689cac1dd08f2b5a9c69 100644 (file)
@@ -2839,6 +2839,7 @@ int r600_copy_cpdma(struct radeon_device *rdev,
        r = radeon_fence_emit(rdev, fence, ring->idx);
        if (r) {
                radeon_ring_unlock_undo(rdev, ring);
+               radeon_semaphore_free(rdev, &sem, NULL);
                return r;
        }
 
@@ -3505,7 +3506,6 @@ int r600_irq_set(struct radeon_device *rdev)
        u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0;
        u32 grbm_int_cntl = 0;
        u32 hdmi0, hdmi1;
-       u32 d1grph = 0, d2grph = 0;
        u32 dma_cntl;
        u32 thermal_int = 0;
 
@@ -3614,8 +3614,8 @@ int r600_irq_set(struct radeon_device *rdev)
        WREG32(CP_INT_CNTL, cp_int_cntl);
        WREG32(DMA_CNTL, dma_cntl);
        WREG32(DxMODE_INT_MASK, mode_int);
-       WREG32(D1GRPH_INTERRUPT_CONTROL, d1grph);
-       WREG32(D2GRPH_INTERRUPT_CONTROL, d2grph);
+       WREG32(D1GRPH_INTERRUPT_CONTROL, DxGRPH_PFLIP_INT_MASK);
+       WREG32(D2GRPH_INTERRUPT_CONTROL, DxGRPH_PFLIP_INT_MASK);
        WREG32(GRBM_INT_CNTL, grbm_int_cntl);
        if (ASIC_IS_DCE3(rdev)) {
                WREG32(DC_HPD1_INT_CONTROL, hpd1);
@@ -3918,6 +3918,14 @@ restart_ih:
                                break;
                        }
                        break;
+               case 9: /* D1 pflip */
+                       DRM_DEBUG("IH: D1 flip\n");
+                       radeon_crtc_handle_flip(rdev, 0);
+                       break;
+               case 11: /* D2 pflip */
+                       DRM_DEBUG("IH: D2 flip\n");
+                       radeon_crtc_handle_flip(rdev, 1);
+                       break;
                case 19: /* HPD/DAC hotplug */
                        switch (src_data) {
                        case 0:
index 53fcb28f5578d76919fa182488b32be8a1c6278a..4969cef44a1911b706e933fb8252397ddd893785 100644 (file)
@@ -489,6 +489,7 @@ int r600_copy_dma(struct radeon_device *rdev,
        r = radeon_fence_emit(rdev, fence, ring->idx);
        if (r) {
                radeon_ring_unlock_undo(rdev, ring);
+               radeon_semaphore_free(rdev, &sem, NULL);
                return r;
        }
 
index b58e1afdda7697e9a2e094c3f07bacc8a1621699..8149e7cf430330095da34f98d27f842832c2c91c 100644 (file)
@@ -730,6 +730,12 @@ struct cik_irq_stat_regs {
        u32 disp_int_cont4;
        u32 disp_int_cont5;
        u32 disp_int_cont6;
+       u32 d1grph_int;
+       u32 d2grph_int;
+       u32 d3grph_int;
+       u32 d4grph_int;
+       u32 d5grph_int;
+       u32 d6grph_int;
 };
 
 union radeon_irq_stat_regs {
@@ -1636,6 +1642,7 @@ struct radeon_vce {
        unsigned                fb_version;
        atomic_t                handles[RADEON_MAX_VCE_HANDLES];
        struct drm_file         *filp[RADEON_MAX_VCE_HANDLES];
+       unsigned                img_size[RADEON_MAX_VCE_HANDLES];
        struct delayed_work     idle_work;
 };
 
@@ -1649,7 +1656,7 @@ int radeon_vce_get_destroy_msg(struct radeon_device *rdev, int ring,
                               uint32_t handle, struct radeon_fence **fence);
 void radeon_vce_free_handles(struct radeon_device *rdev, struct drm_file *filp);
 void radeon_vce_note_usage(struct radeon_device *rdev);
-int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi);
+int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi, unsigned size);
 int radeon_vce_cs_parse(struct radeon_cs_parser *p);
 bool radeon_vce_semaphore_emit(struct radeon_device *rdev,
                               struct radeon_ring *ring,
@@ -2634,7 +2641,8 @@ void r100_pll_errata_after_index(struct radeon_device *rdev);
 #define ASIC_IS_DCE8(rdev) ((rdev->family >= CHIP_BONAIRE))
 #define ASIC_IS_DCE81(rdev) ((rdev->family == CHIP_KAVERI))
 #define ASIC_IS_DCE82(rdev) ((rdev->family == CHIP_BONAIRE))
-#define ASIC_IS_DCE83(rdev) ((rdev->family == CHIP_KABINI))
+#define ASIC_IS_DCE83(rdev) ((rdev->family == CHIP_KABINI) || \
+                            (rdev->family == CHIP_MULLINS))
 
 #define ASIC_IS_LOMBOK(rdev) ((rdev->ddev->pdev->device == 0x6849) || \
                              (rdev->ddev->pdev->device == 0x6850) || \
index b8a24a75d4fff0e48e60b1f078f33e36c5209d94..be20e62dac83c5b6d96bcfc2b44a9140691b7bb8 100644 (file)
@@ -2516,6 +2516,7 @@ int radeon_asic_init(struct radeon_device *rdev)
                break;
        case CHIP_KAVERI:
        case CHIP_KABINI:
+       case CHIP_MULLINS:
                rdev->asic = &kv_asic;
                /* set num crtcs */
                if (rdev->family == CHIP_KAVERI) {
index b3633d9a531703a1cd4189c061a0907e89ee1085..9ab30976287d4c27e0dc94e0cadfa993e6ec77cc 100644 (file)
@@ -196,6 +196,20 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)
                }
        }
 
+       if (!found) {
+               while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
+                       dhandle = ACPI_HANDLE(&pdev->dev);
+                       if (!dhandle)
+                               continue;
+
+                       status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
+                       if (!ACPI_FAILURE(status)) {
+                               found = true;
+                               break;
+                       }
+               }
+       }
+
        if (!found)
                return false;
 
index 2b6e0ebcc13ab5e75b76089dcbcc00eeae08b360..41ecf8a606117caa02954e720af0fb4ad690139e 100644 (file)
@@ -152,6 +152,12 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
                        uint32_t domain = r->write_domain ?
                                r->write_domain : r->read_domains;
 
+                       if (domain & RADEON_GEM_DOMAIN_CPU) {
+                               DRM_ERROR("RADEON_GEM_DOMAIN_CPU is not valid "
+                                         "for command submission\n");
+                               return -EINVAL;
+                       }
+
                        p->relocs[i].domain = domain;
                        if (domain == RADEON_GEM_DOMAIN_VRAM)
                                domain |= RADEON_GEM_DOMAIN_GTT;
@@ -342,10 +348,17 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
                        return -EINVAL;
 
                /* we only support VM on some SI+ rings */
-               if ((p->rdev->asic->ring[p->ring]->cs_parse == NULL) &&
-                  ((p->cs_flags & RADEON_CS_USE_VM) == 0)) {
-                       DRM_ERROR("Ring %d requires VM!\n", p->ring);
-                       return -EINVAL;
+               if ((p->cs_flags & RADEON_CS_USE_VM) == 0) {
+                       if (p->rdev->asic->ring[p->ring]->cs_parse == NULL) {
+                               DRM_ERROR("Ring %d requires VM!\n", p->ring);
+                               return -EINVAL;
+                       }
+               } else {
+                       if (p->rdev->asic->ring[p->ring]->ib_parse == NULL) {
+                               DRM_ERROR("VM not supported on ring %d!\n",
+                                         p->ring);
+                               return -EINVAL;
+                       }
                }
        }
 
index 511fe26198e4a3e5a779af5e7f82bf62be570da6..14671406212f00a65d1af8e7e2b10489f93bbba3 100644 (file)
@@ -99,6 +99,7 @@ static const char radeon_family_name[][16] = {
        "KAVERI",
        "KABINI",
        "HAWAII",
+       "MULLINS",
        "LAST",
 };
 
@@ -1532,11 +1533,6 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
 
        radeon_restore_bios_scratch_regs(rdev);
 
-       if (fbcon) {
-               radeon_fbdev_set_suspend(rdev, 0);
-               console_unlock();
-       }
-
        /* init dig PHYs, disp eng pll */
        if (rdev->is_atom_bios) {
                radeon_atom_encoder_init(rdev);
@@ -1561,6 +1557,12 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
        }
 
        drm_kms_helper_poll_enable(dev);
+
+       if (fbcon) {
+               radeon_fbdev_set_suspend(rdev, 0);
+               console_unlock();
+       }
+
        return 0;
 }
 
index 8d99d5ee8014c4f23e031a31cbeab85bde33d81a..356b733caafeb84093b75ba8ad00191ebfe4c5b5 100644 (file)
@@ -284,6 +284,10 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
        u32 update_pending;
        int vpos, hpos;
 
+       /* can happen during initialization */
+       if (radeon_crtc == NULL)
+               return;
+
        spin_lock_irqsave(&rdev->ddev->event_lock, flags);
        work = radeon_crtc->unpin_work;
        if (work == NULL ||
@@ -826,14 +830,14 @@ static void avivo_reduce_ratio(unsigned *nom, unsigned *den,
 
        /* make sure nominator is large enough */
         if (*nom < nom_min) {
-               tmp = (nom_min + *nom - 1) / *nom;
+               tmp = DIV_ROUND_UP(nom_min, *nom);
                *nom *= tmp;
                *den *= tmp;
        }
 
        /* make sure the denominator is large enough */
        if (*den < den_min) {
-               tmp = (den_min + *den - 1) / *den;
+               tmp = DIV_ROUND_UP(den_min, *den);
                *nom *= tmp;
                *den *= tmp;
        }
@@ -858,7 +862,7 @@ static void avivo_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div,
                                 unsigned *fb_div, unsigned *ref_div)
 {
        /* limit reference * post divider to a maximum */
-       ref_div_max = min(210 / post_div, ref_div_max);
+       ref_div_max = max(min(100 / post_div, ref_div_max), 1u);
 
        /* get matching reference and feedback divider */
        *ref_div = min(max(DIV_ROUND_CLOSEST(den, post_div), 1u), ref_div_max);
@@ -993,6 +997,16 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
        /* this also makes sure that the reference divider is large enough */
        avivo_reduce_ratio(&fb_div, &ref_div, fb_div_min, ref_div_min);
 
+       /* avoid high jitter with small fractional dividers */
+       if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV && (fb_div % 10)) {
+               fb_div_min = max(fb_div_min, (9 - (fb_div % 10)) * 20 + 50);
+               if (fb_div < fb_div_min) {
+                       unsigned tmp = DIV_ROUND_UP(fb_div_min, fb_div);
+                       fb_div *= tmp;
+                       ref_div *= tmp;
+               }
+       }
+
        /* and finally save the result */
        if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
                *fb_div_p = fb_div / 10;
index 9da5da4ffd176907d2b3f9b077e883cd9ab89323..4b7b87f71a6371308a64e78c7289a4e28117ef5f 100644 (file)
@@ -97,6 +97,7 @@ enum radeon_family {
        CHIP_KAVERI,
        CHIP_KABINI,
        CHIP_HAWAII,
+       CHIP_MULLINS,
        CHIP_LAST,
 };
 
index 0cc47f12d9957d916b41acf4d3874fa062313175..eaaedba0467595aaced591c6d70666c75ac97211 100644 (file)
@@ -577,28 +577,29 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
                        return r;
                }
 
-               r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
-               if (r) {
-                       radeon_vm_fini(rdev, &fpriv->vm);
-                       kfree(fpriv);
-                       return r;
-               }
+               if (rdev->accel_working) {
+                       r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
+                       if (r) {
+                               radeon_vm_fini(rdev, &fpriv->vm);
+                               kfree(fpriv);
+                               return r;
+                       }
 
-               /* map the ib pool buffer read only into
-                * virtual address space */
-               bo_va = radeon_vm_bo_add(rdev, &fpriv->vm,
-                                        rdev->ring_tmp_bo.bo);
-               r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET,
-                                         RADEON_VM_PAGE_READABLE |
-                                         RADEON_VM_PAGE_SNOOPED);
+                       /* map the ib pool buffer read only into
+                        * virtual address space */
+                       bo_va = radeon_vm_bo_add(rdev, &fpriv->vm,
+                                                rdev->ring_tmp_bo.bo);
+                       r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET,
+                                                 RADEON_VM_PAGE_READABLE |
+                                                 RADEON_VM_PAGE_SNOOPED);
 
-               radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
-               if (r) {
-                       radeon_vm_fini(rdev, &fpriv->vm);
-                       kfree(fpriv);
-                       return r;
+                       radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
+                       if (r) {
+                               radeon_vm_fini(rdev, &fpriv->vm);
+                               kfree(fpriv);
+                               return r;
+                       }
                }
-
                file_priv->driver_priv = fpriv;
        }
 
@@ -626,13 +627,15 @@ void radeon_driver_postclose_kms(struct drm_device *dev,
                struct radeon_bo_va *bo_va;
                int r;
 
-               r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
-               if (!r) {
-                       bo_va = radeon_vm_bo_find(&fpriv->vm,
-                                                 rdev->ring_tmp_bo.bo);
-                       if (bo_va)
-                               radeon_vm_bo_rmv(rdev, bo_va);
-                       radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
+               if (rdev->accel_working) {
+                       r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
+                       if (!r) {
+                               bo_va = radeon_vm_bo_find(&fpriv->vm,
+                                                         rdev->ring_tmp_bo.bo);
+                               if (bo_va)
+                                       radeon_vm_bo_rmv(rdev, bo_va);
+                               radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
+                       }
                }
 
                radeon_vm_fini(rdev, &fpriv->vm);
index 19bec0dbfa38bf052db75cb52401adfcb29ac986..4faa4d6f9bb4f0616e0575d916069b47fa9389ed 100644 (file)
@@ -458,7 +458,7 @@ int radeon_bo_list_validate(struct radeon_device *rdev,
                         * into account. We don't want to disallow buffer moves
                         * completely.
                         */
-                       if (current_domain != RADEON_GEM_DOMAIN_CPU &&
+                       if ((lobj->alt_domain & current_domain) != 0 &&
                            (domain & current_domain) == 0 && /* will be moved */
                            bytes_moved > bytes_moved_threshold) {
                                /* don't move it */
@@ -699,22 +699,30 @@ int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
        rbo = container_of(bo, struct radeon_bo, tbo);
        radeon_bo_check_tiling(rbo, 0, 0);
        rdev = rbo->rdev;
-       if (bo->mem.mem_type == TTM_PL_VRAM) {
-               size = bo->mem.num_pages << PAGE_SHIFT;
-               offset = bo->mem.start << PAGE_SHIFT;
-               if ((offset + size) > rdev->mc.visible_vram_size) {
-                       /* hurrah the memory is not visible ! */
-                       radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM);
-                       rbo->placement.lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT;
-                       r = ttm_bo_validate(bo, &rbo->placement, false, false);
-                       if (unlikely(r != 0))
-                               return r;
-                       offset = bo->mem.start << PAGE_SHIFT;
-                       /* this should not happen */
-                       if ((offset + size) > rdev->mc.visible_vram_size)
-                               return -EINVAL;
-               }
+       if (bo->mem.mem_type != TTM_PL_VRAM)
+               return 0;
+
+       size = bo->mem.num_pages << PAGE_SHIFT;
+       offset = bo->mem.start << PAGE_SHIFT;
+       if ((offset + size) <= rdev->mc.visible_vram_size)
+               return 0;
+
+       /* hurrah the memory is not visible ! */
+       radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM);
+       rbo->placement.lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT;
+       r = ttm_bo_validate(bo, &rbo->placement, false, false);
+       if (unlikely(r == -ENOMEM)) {
+               radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT);
+               return ttm_bo_validate(bo, &rbo->placement, false, false);
+       } else if (unlikely(r != 0)) {
+               return r;
        }
+
+       offset = bo->mem.start << PAGE_SHIFT;
+       /* this should never happen */
+       if ((offset + size) > rdev->mc.visible_vram_size)
+               return -EINVAL;
+
        return 0;
 }
 
index 6fac8efe8340e2e99f83965201bab056de2997de..53d6e1bb48dc326bb3487fde5f02749df56d4e57 100644 (file)
@@ -361,6 +361,11 @@ static ssize_t radeon_set_pm_profile(struct device *dev,
        struct drm_device *ddev = dev_get_drvdata(dev);
        struct radeon_device *rdev = ddev->dev_private;
 
+       /* Can't set profile when the card is off */
+       if  ((rdev->flags & RADEON_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+               return -EINVAL;
+
        mutex_lock(&rdev->pm.mutex);
        if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
                if (strncmp("default", buf, strlen("default")) == 0)
@@ -409,6 +414,13 @@ static ssize_t radeon_set_pm_method(struct device *dev,
        struct drm_device *ddev = dev_get_drvdata(dev);
        struct radeon_device *rdev = ddev->dev_private;
 
+       /* Can't set method when the card is off */
+       if  ((rdev->flags & RADEON_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) {
+               count = -EINVAL;
+               goto fail;
+       }
+
        /* we don't support the legacy modes with dpm */
        if (rdev->pm.pm_method == PM_METHOD_DPM) {
                count = -EINVAL;
@@ -446,6 +458,10 @@ static ssize_t radeon_get_dpm_state(struct device *dev,
        struct radeon_device *rdev = ddev->dev_private;
        enum radeon_pm_state_type pm = rdev->pm.dpm.user_state;
 
+       if  ((rdev->flags & RADEON_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+               return snprintf(buf, PAGE_SIZE, "off\n");
+
        return snprintf(buf, PAGE_SIZE, "%s\n",
                        (pm == POWER_STATE_TYPE_BATTERY) ? "battery" :
                        (pm == POWER_STATE_TYPE_BALANCED) ? "balanced" : "performance");
@@ -459,6 +475,11 @@ static ssize_t radeon_set_dpm_state(struct device *dev,
        struct drm_device *ddev = dev_get_drvdata(dev);
        struct radeon_device *rdev = ddev->dev_private;
 
+       /* Can't set dpm state when the card is off */
+       if  ((rdev->flags & RADEON_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+               return -EINVAL;
+
        mutex_lock(&rdev->pm.mutex);
        if (strncmp("battery", buf, strlen("battery")) == 0)
                rdev->pm.dpm.user_state = POWER_STATE_TYPE_BATTERY;
@@ -485,6 +506,10 @@ static ssize_t radeon_get_dpm_forced_performance_level(struct device *dev,
        struct radeon_device *rdev = ddev->dev_private;
        enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level;
 
+       if  ((rdev->flags & RADEON_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+               return snprintf(buf, PAGE_SIZE, "off\n");
+
        return snprintf(buf, PAGE_SIZE, "%s\n",
                        (level == RADEON_DPM_FORCED_LEVEL_AUTO) ? "auto" :
                        (level == RADEON_DPM_FORCED_LEVEL_LOW) ? "low" : "high");
@@ -500,6 +525,11 @@ static ssize_t radeon_set_dpm_forced_performance_level(struct device *dev,
        enum radeon_dpm_forced_level level;
        int ret = 0;
 
+       /* Can't force performance level when the card is off */
+       if  ((rdev->flags & RADEON_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+               return -EINVAL;
+
        mutex_lock(&rdev->pm.mutex);
        if (strncmp("low", buf, strlen("low")) == 0) {
                level = RADEON_DPM_FORCED_LEVEL_LOW;
@@ -538,8 +568,14 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev,
                                      char *buf)
 {
        struct radeon_device *rdev = dev_get_drvdata(dev);
+       struct drm_device *ddev = rdev->ddev;
        int temp;
 
+       /* Can't get temperature when the card is off */
+       if  ((rdev->flags & RADEON_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+               return -EINVAL;
+
        if (rdev->asic->pm.get_temperature)
                temp = radeon_get_temperature(rdev);
        else
@@ -1300,6 +1336,7 @@ int radeon_pm_init(struct radeon_device *rdev)
        case CHIP_KABINI:
        case CHIP_KAVERI:
        case CHIP_HAWAII:
+       case CHIP_MULLINS:
                /* DPM requires the RLC, RV770+ dGPU requires SMC */
                if (!rdev->rlc_fw)
                        rdev->pm.pm_method = PM_METHOD_PROFILE;
@@ -1613,8 +1650,12 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data)
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
        struct radeon_device *rdev = dev->dev_private;
+       struct drm_device *ddev = rdev->ddev;
 
-       if (rdev->pm.dpm_enabled) {
+       if  ((rdev->flags & RADEON_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) {
+               seq_printf(m, "PX asic powered off\n");
+       } else if (rdev->pm.dpm_enabled) {
                mutex_lock(&rdev->pm.mutex);
                if (rdev->asic->dpm.debugfs_print_current_performance_level)
                        radeon_dpm_debugfs_print_current_performance_level(rdev, m);
index 58d12938c0b80bf022bc8c5490a8cb660041fa5d..4e7c3269b183644ea87c4879d764eac7fb246e80 100644 (file)
@@ -52,6 +52,7 @@
 #define BONAIRE_RLC_UCODE_SIZE       2048
 #define KB_RLC_UCODE_SIZE            2560
 #define KV_RLC_UCODE_SIZE            2560
+#define ML_RLC_UCODE_SIZE            2560
 
 /* MC */
 #define BTC_MC_UCODE_SIZE            6024
index 5748bdaeacceb2f593bab46448ba5bf49fb940ae..1b65ae2433cd0e4063a546cb9806f6d917ba83a9 100644 (file)
@@ -99,6 +99,7 @@ int radeon_uvd_init(struct radeon_device *rdev)
        case CHIP_KABINI:
        case CHIP_KAVERI:
        case CHIP_HAWAII:
+       case CHIP_MULLINS:
                fw_name = FIRMWARE_BONAIRE;
                break;
 
@@ -465,6 +466,10 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
        cmd = radeon_get_ib_value(p, p->idx) >> 1;
 
        if (cmd < 0x4) {
+               if (end <= start) {
+                       DRM_ERROR("invalid reloc offset %X!\n", offset);
+                       return -EINVAL;
+               }
                if ((end - start) < buf_sizes[cmd]) {
                        DRM_ERROR("buffer (%d) to small (%d / %d)!\n", cmd,
                                  (unsigned)(end - start), buf_sizes[cmd]);
index ced53dd03e7c1f12449850c1eaa2d2568a552750..3971d968af6c0d86d0ba6e6f08f94d26714e17ec 100644 (file)
@@ -66,6 +66,7 @@ int radeon_vce_init(struct radeon_device *rdev)
        case CHIP_BONAIRE:
        case CHIP_KAVERI:
        case CHIP_KABINI:
+       case CHIP_MULLINS:
                fw_name = FIRMWARE_BONAIRE;
                break;
 
@@ -442,13 +443,16 @@ int radeon_vce_get_destroy_msg(struct radeon_device *rdev, int ring,
  * @p: parser context
  * @lo: address of lower dword
  * @hi: address of higher dword
+ * @size: size of checker for relocation buffer
  *
  * Patch relocation inside command stream with real buffer address
  */
-int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi)
+int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi,
+                       unsigned size)
 {
        struct radeon_cs_chunk *relocs_chunk;
-       uint64_t offset;
+       struct radeon_cs_reloc *reloc;
+       uint64_t start, end, offset;
        unsigned idx;
 
        relocs_chunk = &p->chunks[p->chunk_relocs_idx];
@@ -461,14 +465,59 @@ int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi)
                return -EINVAL;
        }
 
-       offset += p->relocs_ptr[(idx / 4)]->gpu_offset;
+       reloc = p->relocs_ptr[(idx / 4)];
+       start = reloc->gpu_offset;
+       end = start + radeon_bo_size(reloc->robj);
+       start += offset;
 
-        p->ib.ptr[lo] = offset & 0xFFFFFFFF;
-        p->ib.ptr[hi] = offset >> 32;
+       p->ib.ptr[lo] = start & 0xFFFFFFFF;
+       p->ib.ptr[hi] = start >> 32;
+
+       if (end <= start) {
+               DRM_ERROR("invalid reloc offset %llX!\n", offset);
+               return -EINVAL;
+       }
+       if ((end - start) < size) {
+               DRM_ERROR("buffer to small (%d / %d)!\n",
+                       (unsigned)(end - start), size);
+               return -EINVAL;
+       }
 
        return 0;
 }
 
+/**
+ * radeon_vce_validate_handle - validate stream handle
+ *
+ * @p: parser context
+ * @handle: handle to validate
+ *
+ * Validates the handle and return the found session index or -EINVAL
+ * we we don't have another free session index.
+ */
+int radeon_vce_validate_handle(struct radeon_cs_parser *p, uint32_t handle)
+{
+       unsigned i;
+
+       /* validate the handle */
+       for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) {
+               if (atomic_read(&p->rdev->vce.handles[i]) == handle)
+                       return i;
+       }
+
+       /* handle not found try to alloc a new one */
+       for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) {
+               if (!atomic_cmpxchg(&p->rdev->vce.handles[i], 0, handle)) {
+                       p->rdev->vce.filp[i] = p->filp;
+                       p->rdev->vce.img_size[i] = 0;
+                       return i;
+               }
+       }
+
+       DRM_ERROR("No more free VCE handles!\n");
+       return -EINVAL;
+}
+
 /**
  * radeon_vce_cs_parse - parse and validate the command stream
  *
@@ -477,8 +526,10 @@ int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi)
  */
 int radeon_vce_cs_parse(struct radeon_cs_parser *p)
 {
-       uint32_t handle = 0;
-       bool destroy = false;
+       int session_idx = -1;
+       bool destroyed = false;
+       uint32_t tmp, handle = 0;
+       uint32_t *size = &tmp;
        int i, r;
 
        while (p->idx < p->chunks[p->chunk_ib_idx].length_dw) {
@@ -490,13 +541,29 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p)
                        return -EINVAL;
                }
 
+               if (destroyed) {
+                       DRM_ERROR("No other command allowed after destroy!\n");
+                       return -EINVAL;
+               }
+
                switch (cmd) {
                case 0x00000001: // session
                        handle = radeon_get_ib_value(p, p->idx + 2);
+                       session_idx = radeon_vce_validate_handle(p, handle);
+                       if (session_idx < 0)
+                               return session_idx;
+                       size = &p->rdev->vce.img_size[session_idx];
                        break;
 
                case 0x00000002: // task info
+                       break;
+
                case 0x01000001: // create
+                       *size = radeon_get_ib_value(p, p->idx + 8) *
+                               radeon_get_ib_value(p, p->idx + 10) *
+                               8 * 3 / 2;
+                       break;
+
                case 0x04000001: // config extension
                case 0x04000002: // pic control
                case 0x04000005: // rate control
@@ -505,23 +572,39 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p)
                        break;
 
                case 0x03000001: // encode
-                       r = radeon_vce_cs_reloc(p, p->idx + 10, p->idx + 9);
+                       r = radeon_vce_cs_reloc(p, p->idx + 10, p->idx + 9,
+                                               *size);
                        if (r)
                                return r;
 
-                       r = radeon_vce_cs_reloc(p, p->idx + 12, p->idx + 11);
+                       r = radeon_vce_cs_reloc(p, p->idx + 12, p->idx + 11,
+                                               *size / 3);
                        if (r)
                                return r;
                        break;
 
                case 0x02000001: // destroy
-                       destroy = true;
+                       destroyed = true;
                        break;
 
                case 0x05000001: // context buffer
+                       r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2,
+                                               *size * 2);
+                       if (r)
+                               return r;
+                       break;
+
                case 0x05000004: // video bitstream buffer
+                       tmp = radeon_get_ib_value(p, p->idx + 4);
+                       r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2,
+                                               tmp);
+                       if (r)
+                               return r;
+                       break;
+
                case 0x05000005: // feedback buffer
-                       r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2);
+                       r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2,
+                                               4096);
                        if (r)
                                return r;
                        break;
@@ -531,33 +614,21 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p)
                        return -EINVAL;
                }
 
+               if (session_idx == -1) {
+                       DRM_ERROR("no session command at start of IB\n");
+                       return -EINVAL;
+               }
+
                p->idx += len / 4;
        }
 
-       if (destroy) {
+       if (destroyed) {
                /* IB contains a destroy msg, free the handle */
                for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i)
                        atomic_cmpxchg(&p->rdev->vce.handles[i], handle, 0);
-
-               return 0;
-        }
-
-       /* create or encode, validate the handle */
-       for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) {
-               if (atomic_read(&p->rdev->vce.handles[i]) == handle)
-                       return 0;
        }
 
-       /* handle not found try to alloc a new one */
-       for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) {
-               if (!atomic_cmpxchg(&p->rdev->vce.handles[i], 0, handle)) {
-                       p->rdev->vce.filp[i] = p->filp;
-                       return 0;
-               }
-       }
-
-       DRM_ERROR("No more free VCE handles!\n");
-       return -EINVAL;
+       return 0;
 }
 
 /**
index 2aae6ce49d3286888ea22347b60d71cc5220eef4..1f426696de36e200453af920ea8fb7256d5151b1 100644 (file)
@@ -130,10 +130,10 @@ struct radeon_cs_reloc *radeon_vm_get_bos(struct radeon_device *rdev,
                                          struct list_head *head)
 {
        struct radeon_cs_reloc *list;
-       unsigned i, idx, size;
+       unsigned i, idx;
 
-       size = (radeon_vm_num_pdes(rdev) + 1) * sizeof(struct radeon_cs_reloc);
-       list = kmalloc(size, GFP_KERNEL);
+       list = kmalloc_array(vm->max_pde_used + 1,
+                            sizeof(struct radeon_cs_reloc), GFP_KERNEL);
        if (!list)
                return NULL;
 
@@ -595,7 +595,7 @@ int radeon_vm_update_page_directory(struct radeon_device *rdev,
        ndw = 64;
 
        /* assume the worst case */
-       ndw += vm->max_pde_used * 12;
+       ndw += vm->max_pde_used * 16;
 
        /* update too big for an IB */
        if (ndw > 0xfffff)
index aca8cbe8a335dce1d13487c60e13f3193630fec7..bbf2e076ee457816924a736c57d2192cabba88ac 100644 (file)
@@ -86,6 +86,7 @@ int rv770_copy_dma(struct radeon_device *rdev,
        r = radeon_fence_emit(rdev, fence, ring->idx);
        if (r) {
                radeon_ring_unlock_undo(rdev, ring);
+               radeon_semaphore_free(rdev, &sem, NULL);
                return r;
        }
 
index ac708e006180d3467cfe0478c2484eeb64a2df68..22a63c98ba14c688ab259fa666fe3e5d111fb792 100644 (file)
@@ -5780,7 +5780,6 @@ int si_irq_set(struct radeon_device *rdev)
        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;
        u32 grbm_int_cntl = 0;
-       u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0;
        u32 dma_cntl, dma_cntl1;
        u32 thermal_int = 0;
 
@@ -5919,16 +5918,22 @@ int si_irq_set(struct radeon_device *rdev)
        }
 
        if (rdev->num_crtc >= 2) {
-               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1);
-               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2);
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET,
+                      GRPH_PFLIP_INT_MASK);
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET,
+                      GRPH_PFLIP_INT_MASK);
        }
        if (rdev->num_crtc >= 4) {
-               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3);
-               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4);
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET,
+                      GRPH_PFLIP_INT_MASK);
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET,
+                      GRPH_PFLIP_INT_MASK);
        }
        if (rdev->num_crtc >= 6) {
-               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5);
-               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6);
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET,
+                      GRPH_PFLIP_INT_MASK);
+               WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET,
+                      GRPH_PFLIP_INT_MASK);
        }
 
        if (!ASIC_IS_NODCE(rdev)) {
@@ -6292,6 +6297,15 @@ restart_ih:
                                break;
                        }
                        break;
+               case 8: /* D1 page flip */
+               case 10: /* D2 page flip */
+               case 12: /* D3 page flip */
+               case 14: /* D4 page flip */
+               case 16: /* D5 page flip */
+               case 18: /* D6 page flip */
+                       DRM_DEBUG("IH: D%d flip\n", ((src_id - 8) >> 1) + 1);
+                       radeon_crtc_handle_flip(rdev, (src_id - 8) >> 1);
+                       break;
                case 42: /* HPD hotplug */
                        switch (src_data) {
                        case 0:
index cf0fdad8c278ef6921bbab3677c2cd596bcf1575..de0ca070122f62ee0c8b7fcc6d8db0360adfb948 100644 (file)
@@ -213,6 +213,7 @@ int si_copy_dma(struct radeon_device *rdev,
        r = radeon_fence_emit(rdev, fence, ring->idx);
        if (r) {
                radeon_ring_unlock_undo(rdev, ring);
+               radeon_semaphore_free(rdev, &sem, NULL);
                return r;
        }
 
index 683532f849311d1ca19de3daccb168b368d4c0b5..7321283602ce0c1d8429193efe4221ba26a33761 100644 (file)
 #define                SPLL_CHG_STATUS                         (1 << 1)
 #define        SPLL_CNTL_MODE                                  0x618
 #define                SPLL_SW_DIR_CONTROL                     (1 << 0)
-#      define SPLL_REFCLK_SEL(x)                       ((x) << 8)
-#      define SPLL_REFCLK_SEL_MASK                     0xFF00
+#      define SPLL_REFCLK_SEL(x)                       ((x) << 26)
+#      define SPLL_REFCLK_SEL_MASK                     (3 << 26)
 
 #define        CG_SPLL_SPREAD_SPECTRUM                         0x620
 #define                SSEN                                    (1 << 0)
index 0a243f0e5d6889129fff88d3f5a3656450dd14cf..be42c8125203b22bd62d9fc4be8510672ba577b3 100644 (file)
@@ -83,7 +83,10 @@ int uvd_v1_0_init(struct radeon_device *rdev)
        int r;
 
        /* raise clocks while booting up the VCPU */
-       radeon_set_uvd_clocks(rdev, 53300, 40000);
+       if (rdev->family < CHIP_RV740)
+               radeon_set_uvd_clocks(rdev, 10000, 10000);
+       else
+               radeon_set_uvd_clocks(rdev, 53300, 40000);
 
        r = uvd_v1_0_start(rdev);
        if (r)
@@ -407,7 +410,10 @@ int uvd_v1_0_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
        struct radeon_fence *fence = NULL;
        int r;
 
-       r = radeon_set_uvd_clocks(rdev, 53300, 40000);
+       if (rdev->family < CHIP_RV740)
+               r = radeon_set_uvd_clocks(rdev, 10000, 10000);
+       else
+               r = radeon_set_uvd_clocks(rdev, 53300, 40000);
        if (r) {
                DRM_ERROR("radeon: failed to raise UVD clocks (%d).\n", r);
                return r;
index 10a2c08664596a3c43d1687cab911ad3fc3ab970..da52279de939652c9f1cffc1f60cf4308ce795ea 100644 (file)
@@ -1253,7 +1253,8 @@ EXPORT_SYMBOL_GPL(hid_output_report);
 
 static int hid_report_len(struct hid_report *report)
 {
-       return ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7;
+       /* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */
+       return ((report->size - 1) >> 3) + 1 + (report->id > 0);
 }
 
 /*
@@ -1266,7 +1267,7 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags)
         * of implement() working on 8 byte chunks
         */
 
-       int len = hid_report_len(report);
+       int len = hid_report_len(report) + 7;
 
        return kmalloc(len, flags);
 }
index c8af7202c28da3027e73cfd0a9d8b95d6036dbe1..34bb2205d2ea21bed4593d2b50a3f9e9e3e5b52f 100644 (file)
 
 #define USB_VENDOR_ID_DREAM_CHEEKY     0x1d34
 
+#define USB_VENDOR_ID_ELITEGROUP       0x03fc
+#define USB_DEVICE_ID_ELITEGROUP_05D8  0x05d8
+
 #define USB_VENDOR_ID_ELO              0x04E7
 #define USB_DEVICE_ID_ELO_TS2515       0x0022
 #define USB_DEVICE_ID_ELO_TS2700       0x0020
 #define USB_DEVICE_ID_SYNAPTICS_LTS2   0x1d10
 #define USB_DEVICE_ID_SYNAPTICS_HD     0x0ac3
 #define USB_DEVICE_ID_SYNAPTICS_QUAD_HD        0x1ac3
+#define USB_DEVICE_ID_SYNAPTICS_TP_V103        0x5710
+
+#define USB_VENDOR_ID_TEXAS_INSTRUMENTS        0x2047
+#define USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA    0x0855
 
 #define USB_VENDOR_ID_THINGM           0x27b8
 #define USB_DEVICE_ID_BLINK1           0x01ed
index 35278e43c7a48d1999283c21f0f60cceccbc3b84..51e25b9407f259dfa219012aa9f28b274f764f27 100644 (file)
@@ -1155,6 +1155,11 @@ static const struct hid_device_id mt_devices[] = {
                MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
                        USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
 
+       /* Elitegroup panel */
+       { .driver_data = MT_CLS_SERIAL,
+               MT_USB_DEVICE(USB_VENDOR_ID_ELITEGROUP,
+                       USB_DEVICE_ID_ELITEGROUP_05D8) },
+
        /* Flatfrog Panels */
        { .driver_data = MT_CLS_FLATFROG,
                MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG,
index af8244b1c1f428dab026544802ca951089a02fd1..be14b5690e942d5a1c47d9e2f45b706f804d2162 100644 (file)
@@ -708,6 +708,9 @@ static const struct hid_device_id sensor_hub_devices[] = {
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0,
                        USB_DEVICE_ID_STM_HID_SENSOR),
                        .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
+       { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_TEXAS_INSTRUMENTS,
+                       USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA),
+                       .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID,
                     HID_ANY_ID) },
        { }
index dbd83878ff99ec029a1cda07b265ddcd27418710..8e4ddb369883257384a2d0fb315c4ab231eb486a 100644 (file)
@@ -119,6 +119,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103, HID_QUIRK_NO_INIT_REPORTS },
 
        { 0, 0 }
 };
index bc196f49ec53be2e13959a9ebca9aa9c82edcfff..4af0da96c2e22a6d18474cf60e34649acc11167b 100644 (file)
@@ -1053,7 +1053,7 @@ config SENSORS_PC87427
 
 config SENSORS_NTC_THERMISTOR
        tristate "NTC thermistor support"
-       depends on (!OF && !IIO) || (OF && IIO)
+       depends on !OF || IIO=n || IIO
        help
          This driver supports NTC thermistors sensor reading and its
          interpretation. The driver can also monitor the temperature and
index 90ec1173b8a125c629542e079cac66872ea60ec4..01723f04fe45bfa449b60d07a05cd905cc9ccc98 100644 (file)
@@ -163,7 +163,7 @@ static ssize_t store_hyst(struct device *dev,
        if (retval < 0)
                goto fail;
 
-       hyst = val - retval * 1000;
+       hyst = retval * 1000 - val;
        hyst = DIV_ROUND_CLOSEST(hyst, 1000);
        if (hyst < 0 || hyst > 255) {
                retval = -ERANGE;
@@ -330,7 +330,7 @@ static int emc1403_detect(struct i2c_client *client,
        }
 
        id = i2c_smbus_read_byte_data(client, THERMAL_REVISION_REG);
-       if (id != 0x01)
+       if (id < 0x01 || id > 0x04)
                return -ENODEV;
 
        return 0;
@@ -355,9 +355,9 @@ static int emc1403_probe(struct i2c_client *client,
        if (id->driver_data)
                data->groups[1] = &emc1404_group;
 
-       hwmon_dev = hwmon_device_register_with_groups(&client->dev,
-                                                     client->name, data,
-                                                     data->groups);
+       hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
+                                                          client->name, data,
+                                                          data->groups);
        if (IS_ERR(hwmon_dev))
                return PTR_ERR(hwmon_dev);
 
index 8a17f01e8672065d7099e4c3ae156f93705eade4..e76feb86a1d4c0b07ab773675ef1244b88ee9b98 100644 (file)
@@ -44,6 +44,7 @@ struct ntc_compensation {
        unsigned int    ohm;
 };
 
+/* Order matters, ntc_match references the entries by index */
 static const struct platform_device_id ntc_thermistor_id[] = {
        { "ncp15wb473", TYPE_NCPXXWB473 },
        { "ncp18wb473", TYPE_NCPXXWB473 },
@@ -141,7 +142,7 @@ struct ntc_data {
        char name[PLATFORM_NAME_SIZE];
 };
 
-#ifdef CONFIG_OF
+#if defined(CONFIG_OF) && IS_ENABLED(CONFIG_IIO)
 static int ntc_adc_iio_read(struct ntc_thermistor_platform_data *pdata)
 {
        struct iio_channel *channel = pdata->chan;
@@ -163,15 +164,15 @@ static int ntc_adc_iio_read(struct ntc_thermistor_platform_data *pdata)
 
 static const struct of_device_id ntc_match[] = {
        { .compatible = "ntc,ncp15wb473",
-               .data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
+               .data = &ntc_thermistor_id[0] },
        { .compatible = "ntc,ncp18wb473",
-               .data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
+               .data = &ntc_thermistor_id[1] },
        { .compatible = "ntc,ncp21wb473",
-               .data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
+               .data = &ntc_thermistor_id[2] },
        { .compatible = "ntc,ncp03wb473",
-               .data = &ntc_thermistor_id[TYPE_NCPXXWB473] },
+               .data = &ntc_thermistor_id[3] },
        { .compatible = "ntc,ncp15wl333",
-               .data = &ntc_thermistor_id[TYPE_NCPXXWL333] },
+               .data = &ntc_thermistor_id[4] },
        { },
 };
 MODULE_DEVICE_TABLE(of, ntc_match);
@@ -223,6 +224,8 @@ ntc_thermistor_parse_dt(struct platform_device *pdev)
        return NULL;
 }
 
+#define ntc_match      NULL
+
 static void ntc_iio_channel_release(struct ntc_thermistor_platform_data *pdata)
 { }
 #endif
index 22e92c3d3d07448cea9aa37fcc4ad6c612570e13..3c20e4bd6dd1380238df20f06941828ec84aadd0 100644 (file)
@@ -422,6 +422,9 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
         */
        dw_writel(dev, msgs[dev->msg_write_idx].addr | ic_tar, DW_IC_TAR);
 
+       /* enforce disabled interrupts (due to HW issues) */
+       i2c_dw_disable_int(dev);
+
        /* Enable the adapter */
        __i2c_dw_enable(dev, true);
 
index 28cbe1b2a2ec2958547b843d2f86d672fedb5e0b..32c85e9ecdaeb141f0653c3a7e8c85784a1140ce 100644 (file)
@@ -999,7 +999,7 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
 
        dev->virtbase = devm_ioremap(&adev->dev, adev->res.start,
                                resource_size(&adev->res));
-       if (IS_ERR(dev->virtbase)) {
+       if (!dev->virtbase) {
                ret = -ENOMEM;
                goto err_no_mem;
        }
index 1b4cf14f1106aac597b1ab0346ed848e2139ba22..2a5efb5b487cdc2e4fb8774e94167f6af53ca7d8 100644 (file)
@@ -479,7 +479,7 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,
        int ret, idx;
 
        ret = pm_runtime_get_sync(qup->dev);
-       if (ret)
+       if (ret < 0)
                goto out;
 
        writel(1, qup->base + QUP_SW_RESET);
index d4fa8eba6e9d2e40e11cb0ccba5ee64606dd8fff..06d47aafbb79c75a18a66e12964544a9a2b3496f 100644 (file)
@@ -561,6 +561,12 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
 
        ret = -EINVAL;
        for (i = 0; i < num; i++) {
+               /* This HW can't send STOP after address phase */
+               if (msgs[i].len == 0) {
+                       ret = -EOPNOTSUPP;
+                       break;
+               }
+
                /*-------------- spin lock -----------------*/
                spin_lock_irqsave(&priv->lock, flags);
 
@@ -625,7 +631,8 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
 
 static u32 rcar_i2c_func(struct i2c_adapter *adap)
 {
-       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+       /* This HW can't do SMBUS_QUICK and NOSTART */
+       return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
 }
 
 static const struct i2c_algorithm rcar_i2c_algo = {
index ae4491062e411a83a5729a1e267e2430f23f069c..bb3a9964f7e00c2b2c604e32490b0c5f015c4bfe 100644 (file)
@@ -1276,10 +1276,10 @@ static int s3c24xx_i2c_resume(struct device *dev)
        struct platform_device *pdev = to_platform_device(dev);
        struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
 
-       i2c->suspended = 0;
        clk_prepare_enable(i2c->clk);
        s3c24xx_i2c_init(i2c);
        clk_disable_unprepare(i2c->clk);
+       i2c->suspended = 0;
 
        return 0;
 }
index d86196cfe4b47091add5d756da6d3dbf7fded9eb..24c28e3f93a3c960b7fd5c51e9f5348e003ababf 100644 (file)
@@ -106,7 +106,7 @@ config AT91_ADC
          Say yes here to build support for Atmel AT91 ADC.
 
 config EXYNOS_ADC
-       bool "Exynos ADC driver support"
+       tristate "Exynos ADC driver support"
        depends on OF
        help
          Core support for the ADC block found in the Samsung EXYNOS series
@@ -114,7 +114,7 @@ config EXYNOS_ADC
          this resource.
 
 config LP8788_ADC
-       bool "LP8788 ADC driver"
+       tristate "LP8788 ADC driver"
        depends on MFD_LP8788
        help
          Say yes here to build support for TI LP8788 ADC.
index d25b262193a7d4bccad40a42b79685cf4956e6fc..affa93f517893b1c6db2ece1c1e83afeea1828aa 100644 (file)
@@ -344,7 +344,7 @@ static int exynos_adc_probe(struct platform_device *pdev)
 
        exynos_adc_hw_init(info);
 
-       ret = of_platform_populate(np, exynos_adc_match, NULL, &pdev->dev);
+       ret = of_platform_populate(np, exynos_adc_match, NULL, &indio_dev->dev);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed adding child nodes\n");
                goto err_of_populate;
@@ -353,7 +353,7 @@ static int exynos_adc_probe(struct platform_device *pdev)
        return 0;
 
 err_of_populate:
-       device_for_each_child(&pdev->dev, NULL,
+       device_for_each_child(&indio_dev->dev, NULL,
                                exynos_adc_remove_devices);
        regulator_disable(info->vdd);
        clk_disable_unprepare(info->clk);
@@ -369,7 +369,7 @@ static int exynos_adc_remove(struct platform_device *pdev)
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
        struct exynos_adc *info = iio_priv(indio_dev);
 
-       device_for_each_child(&pdev->dev, NULL,
+       device_for_each_child(&indio_dev->dev, NULL,
                                exynos_adc_remove_devices);
        regulator_disable(info->vdd);
        clk_disable_unprepare(info->clk);
index cb9f96b446a55cd138f129db3443d44821b32781..d8ad606c7cd0c7e054d3764afe1b9edb069aaed7 100644 (file)
@@ -660,6 +660,7 @@ static int inv_mpu_probe(struct i2c_client *client,
 {
        struct inv_mpu6050_state *st;
        struct iio_dev *indio_dev;
+       struct inv_mpu6050_platform_data *pdata;
        int result;
 
        if (!i2c_check_functionality(client->adapter,
@@ -672,8 +673,10 @@ static int inv_mpu_probe(struct i2c_client *client,
 
        st = iio_priv(indio_dev);
        st->client = client;
-       st->plat_data = *(struct inv_mpu6050_platform_data
-                               *)dev_get_platdata(&client->dev);
+       pdata = (struct inv_mpu6050_platform_data
+                       *)dev_get_platdata(&client->dev);
+       if (pdata)
+               st->plat_data = *pdata;
        /* power is turned on inside check chip type*/
        result = inv_check_and_setup_chip(st, id);
        if (result)
index 1b6dbe156a3708692a743cd58fc3351d4b01e533..199c7896f08188ca40fa9cd30462f0631d387338 100644 (file)
@@ -48,6 +48,7 @@
 
 #include <linux/mlx4/driver.h>
 #include <linux/mlx4/cmd.h>
+#include <linux/mlx4/qp.h>
 
 #include "mlx4_ib.h"
 #include "user.h"
@@ -1614,6 +1615,53 @@ static int mlx4_ib_inet6_event(struct notifier_block *this, unsigned long event,
 }
 #endif
 
+#define MLX4_IB_INVALID_MAC    ((u64)-1)
+static void mlx4_ib_update_qps(struct mlx4_ib_dev *ibdev,
+                              struct net_device *dev,
+                              int port)
+{
+       u64 new_smac = 0;
+       u64 release_mac = MLX4_IB_INVALID_MAC;
+       struct mlx4_ib_qp *qp;
+
+       read_lock(&dev_base_lock);
+       new_smac = mlx4_mac_to_u64(dev->dev_addr);
+       read_unlock(&dev_base_lock);
+
+       mutex_lock(&ibdev->qp1_proxy_lock[port - 1]);
+       qp = ibdev->qp1_proxy[port - 1];
+       if (qp) {
+               int new_smac_index;
+               u64 old_smac = qp->pri.smac;
+               struct mlx4_update_qp_params update_params;
+
+               if (new_smac == old_smac)
+                       goto unlock;
+
+               new_smac_index = mlx4_register_mac(ibdev->dev, port, new_smac);
+
+               if (new_smac_index < 0)
+                       goto unlock;
+
+               update_params.smac_index = new_smac_index;
+               if (mlx4_update_qp(ibdev->dev, &qp->mqp, MLX4_UPDATE_QP_SMAC,
+                                  &update_params)) {
+                       release_mac = new_smac;
+                       goto unlock;
+               }
+
+               qp->pri.smac = new_smac;
+               qp->pri.smac_index = new_smac_index;
+
+               release_mac = old_smac;
+       }
+
+unlock:
+       mutex_unlock(&ibdev->qp1_proxy_lock[port - 1]);
+       if (release_mac != MLX4_IB_INVALID_MAC)
+               mlx4_unregister_mac(ibdev->dev, port, release_mac);
+}
+
 static void mlx4_ib_get_dev_addr(struct net_device *dev,
                                 struct mlx4_ib_dev *ibdev, u8 port)
 {
@@ -1689,9 +1737,13 @@ static int mlx4_ib_init_gid_table(struct mlx4_ib_dev *ibdev)
        return 0;
 }
 
-static void mlx4_ib_scan_netdevs(struct mlx4_ib_dev *ibdev)
+static void mlx4_ib_scan_netdevs(struct mlx4_ib_dev *ibdev,
+                                struct net_device *dev,
+                                unsigned long event)
+
 {
        struct mlx4_ib_iboe *iboe;
+       int update_qps_port = -1;
        int port;
 
        iboe = &ibdev->iboe;
@@ -1719,6 +1771,11 @@ static void mlx4_ib_scan_netdevs(struct mlx4_ib_dev *ibdev)
                }
                curr_master = iboe->masters[port - 1];
 
+               if (dev == iboe->netdevs[port - 1] &&
+                   (event == NETDEV_CHANGEADDR || event == NETDEV_REGISTER ||
+                    event == NETDEV_UP || event == NETDEV_CHANGE))
+                       update_qps_port = port;
+
                if (curr_netdev) {
                        port_state = (netif_running(curr_netdev) && netif_carrier_ok(curr_netdev)) ?
                                                IB_PORT_ACTIVE : IB_PORT_DOWN;
@@ -1752,6 +1809,9 @@ static void mlx4_ib_scan_netdevs(struct mlx4_ib_dev *ibdev)
        }
 
        spin_unlock(&iboe->lock);
+
+       if (update_qps_port > 0)
+               mlx4_ib_update_qps(ibdev, dev, update_qps_port);
 }
 
 static int mlx4_ib_netdev_event(struct notifier_block *this,
@@ -1764,7 +1824,7 @@ static int mlx4_ib_netdev_event(struct notifier_block *this,
                return NOTIFY_DONE;
 
        ibdev = container_of(this, struct mlx4_ib_dev, iboe.nb);
-       mlx4_ib_scan_netdevs(ibdev);
+       mlx4_ib_scan_netdevs(ibdev, dev, event);
 
        return NOTIFY_DONE;
 }
@@ -2043,6 +2103,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
                goto err_map;
 
        for (i = 0; i < ibdev->num_ports; ++i) {
+               mutex_init(&ibdev->qp1_proxy_lock[i]);
                if (mlx4_ib_port_link_layer(&ibdev->ib_dev, i + 1) ==
                                                IB_LINK_LAYER_ETHERNET) {
                        err = mlx4_counter_alloc(ibdev->dev, &ibdev->counters[i]);
@@ -2126,7 +2187,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
                for (i = 1 ; i <= ibdev->num_ports ; ++i)
                        reset_gid_table(ibdev, i);
                rtnl_lock();
-               mlx4_ib_scan_netdevs(ibdev);
+               mlx4_ib_scan_netdevs(ibdev, NULL, 0);
                rtnl_unlock();
                mlx4_ib_init_gid_table(ibdev);
        }
index f589522fddfd9efa4e32fdd0a7e8f63e49a54927..66b0b7dbd9f41cac95cfb76b4e766249e1abd83b 100644 (file)
@@ -522,6 +522,9 @@ struct mlx4_ib_dev {
        int steer_qpn_count;
        int steer_qpn_base;
        int steering_support;
+       struct mlx4_ib_qp      *qp1_proxy[MLX4_MAX_PORTS];
+       /* lock when destroying qp1_proxy and getting netdev events */
+       struct mutex            qp1_proxy_lock[MLX4_MAX_PORTS];
 };
 
 struct ib_event_work {
index 41308af4163c3dc852adc23f983bdd86d279374e..dc57482ae7af2b2ed8935676a67b459847b3302c 100644 (file)
@@ -1132,6 +1132,12 @@ int mlx4_ib_destroy_qp(struct ib_qp *qp)
        if (is_qp0(dev, mqp))
                mlx4_CLOSE_PORT(dev->dev, mqp->port);
 
+       if (dev->qp1_proxy[mqp->port - 1] == mqp) {
+               mutex_lock(&dev->qp1_proxy_lock[mqp->port - 1]);
+               dev->qp1_proxy[mqp->port - 1] = NULL;
+               mutex_unlock(&dev->qp1_proxy_lock[mqp->port - 1]);
+       }
+
        pd = get_pd(mqp);
        destroy_qp_common(dev, mqp, !!pd->ibpd.uobject);
 
@@ -1646,6 +1652,8 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
                                err = handle_eth_ud_smac_index(dev, qp, (u8 *)attr->smac, context);
                                if (err)
                                        return -EINVAL;
+                               if (qp->mlx4_ib_qp_type == MLX4_IB_QPT_PROXY_GSI)
+                                       dev->qp1_proxy[qp->port - 1] = qp;
                        }
                }
        }
index c98fdb185931644bd3ed92d337f85aa0d2517149..a1710465faaf2345ae9c88755790e3e74a6e76e8 100644 (file)
@@ -28,6 +28,7 @@
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
 #include <target/iscsi/iscsi_transport.h>
+#include <linux/semaphore.h>
 
 #include "isert_proto.h"
 #include "ib_isert.h"
@@ -561,7 +562,15 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
        struct isert_device *device;
        struct ib_device *ib_dev = cma_id->device;
        int ret = 0;
-       u8 pi_support = np->tpg_np->tpg->tpg_attrib.t10_pi;
+       u8 pi_support;
+
+       spin_lock_bh(&np->np_thread_lock);
+       if (!np->enabled) {
+               spin_unlock_bh(&np->np_thread_lock);
+               pr_debug("iscsi_np is not enabled, reject connect request\n");
+               return rdma_reject(cma_id, NULL, 0);
+       }
+       spin_unlock_bh(&np->np_thread_lock);
 
        pr_debug("Entering isert_connect_request cma_id: %p, context: %p\n",
                 cma_id, cma_id->context);
@@ -652,6 +661,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
                goto out_mr;
        }
 
+       pi_support = np->tpg_np->tpg->tpg_attrib.t10_pi;
        if (pi_support && !device->pi_capable) {
                pr_err("Protection information requested but not supported\n");
                ret = -EINVAL;
@@ -663,11 +673,11 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
                goto out_conn_dev;
 
        mutex_lock(&isert_np->np_accept_mutex);
-       list_add_tail(&isert_np->np_accept_list, &isert_conn->conn_accept_node);
+       list_add_tail(&isert_conn->conn_accept_node, &isert_np->np_accept_list);
        mutex_unlock(&isert_np->np_accept_mutex);
 
-       pr_debug("isert_connect_request() waking up np_accept_wq: %p\n", np);
-       wake_up(&isert_np->np_accept_wq);
+       pr_debug("isert_connect_request() up np_sem np: %p\n", np);
+       up(&isert_np->np_sem);
        return 0;
 
 out_conn_dev:
@@ -2999,7 +3009,7 @@ isert_setup_np(struct iscsi_np *np,
                pr_err("Unable to allocate struct isert_np\n");
                return -ENOMEM;
        }
-       init_waitqueue_head(&isert_np->np_accept_wq);
+       sema_init(&isert_np->np_sem, 0);
        mutex_init(&isert_np->np_accept_mutex);
        INIT_LIST_HEAD(&isert_np->np_accept_list);
        init_completion(&isert_np->np_login_comp);
@@ -3047,18 +3057,6 @@ out:
        return ret;
 }
 
-static int
-isert_check_accept_queue(struct isert_np *isert_np)
-{
-       int empty;
-
-       mutex_lock(&isert_np->np_accept_mutex);
-       empty = list_empty(&isert_np->np_accept_list);
-       mutex_unlock(&isert_np->np_accept_mutex);
-
-       return empty;
-}
-
 static int
 isert_rdma_accept(struct isert_conn *isert_conn)
 {
@@ -3151,16 +3149,14 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
        int max_accept = 0, ret;
 
 accept_wait:
-       ret = wait_event_interruptible(isert_np->np_accept_wq,
-                       !isert_check_accept_queue(isert_np) ||
-                       np->np_thread_state == ISCSI_NP_THREAD_RESET);
+       ret = down_interruptible(&isert_np->np_sem);
        if (max_accept > 5)
                return -ENODEV;
 
        spin_lock_bh(&np->np_thread_lock);
        if (np->np_thread_state == ISCSI_NP_THREAD_RESET) {
                spin_unlock_bh(&np->np_thread_lock);
-               pr_err("ISCSI_NP_THREAD_RESET for isert_accept_np\n");
+               pr_debug("ISCSI_NP_THREAD_RESET for isert_accept_np\n");
                return -ENODEV;
        }
        spin_unlock_bh(&np->np_thread_lock);
index 4c072ae34c01a3021e57cb5378a3949b97d0876c..da6612e6800004b0984880d54ef57bcaab1b0be1 100644 (file)
@@ -182,7 +182,7 @@ struct isert_device {
 };
 
 struct isert_np {
-       wait_queue_head_t       np_accept_wq;
+       struct semaphore        np_sem;
        struct rdma_cm_id       *np_cm_id;
        struct mutex            np_accept_mutex;
        struct list_head        np_accept_list;
index 76842d7dc2e3dac1c8964e22141f0de8c20e1d39..ffc7ad3a2c881fefa35e2aeee4a243445a4aaa5f 100644 (file)
@@ -71,7 +71,7 @@ config KEYBOARD_ATKBD
        default y
        select SERIO
        select SERIO_LIBPS2
-       select SERIO_I8042 if X86
+       select SERIO_I8042 if ARCH_MIGHT_HAVE_PC_SERIO
        select SERIO_GSCPS2 if GSC
        help
          Say Y here if you want to use a standard AT or PS/2 keyboard. Usually
index 2626773ff29b956de97d5c62d383e36e13ee4868..2dd1d0dd4f7de03233752e57704ff60c17e6d992 100644 (file)
@@ -243,6 +243,12 @@ static void (*atkbd_platform_fixup)(struct atkbd *, const void *data);
 static void *atkbd_platform_fixup_data;
 static unsigned int (*atkbd_platform_scancode_fixup)(struct atkbd *, unsigned int);
 
+/*
+ * Certain keyboards to not like ATKBD_CMD_RESET_DIS and stop responding
+ * to many commands until full reset (ATKBD_CMD_RESET_BAT) is performed.
+ */
+static bool atkbd_skip_deactivate;
+
 static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
                                ssize_t (*handler)(struct atkbd *, char *));
 static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count,
@@ -768,7 +774,8 @@ static int atkbd_probe(struct atkbd *atkbd)
  * Make sure nothing is coming from the keyboard and disturbs our
  * internal state.
  */
-       atkbd_deactivate(atkbd);
+       if (!atkbd_skip_deactivate)
+               atkbd_deactivate(atkbd);
 
        return 0;
 }
@@ -1638,6 +1645,12 @@ static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id)
        return 1;
 }
 
+static int __init atkbd_deactivate_fixup(const struct dmi_system_id *id)
+{
+       atkbd_skip_deactivate = true;
+       return 1;
+}
+
 static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = {
        {
                .matches = {
@@ -1775,6 +1788,20 @@ static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = {
                .callback = atkbd_setup_scancode_fixup,
                .driver_data = atkbd_oqo_01plus_scancode_fixup,
        },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LW25-B7HV"),
+               },
+               .callback = atkbd_deactivate_fixup,
+       },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "P1-J273B"),
+               },
+               .callback = atkbd_deactivate_fixup,
+       },
        { }
 };
 
index d8241ba0afa0737b5779371563c5623969931df5..a15063bea70020bc44b060a5e9aff8e8133de09e 100644 (file)
@@ -111,6 +111,8 @@ struct pxa27x_keypad {
        unsigned short keycodes[MAX_KEYPAD_KEYS];
        int rotary_rel_code[2];
 
+       unsigned int row_shift;
+
        /* state row bits of each column scan */
        uint32_t matrix_key_state[MAX_MATRIX_KEY_COLS];
        uint32_t direct_key_state;
@@ -467,7 +469,8 @@ scan:
                        if ((bits_changed & (1 << row)) == 0)
                                continue;
 
-                       code = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);
+                       code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
+
                        input_event(input_dev, EV_MSC, MSC_SCAN, code);
                        input_report_key(input_dev, keypad->keycodes[code],
                                         new_state[col] & (1 << row));
@@ -802,6 +805,8 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
                goto failed_put_clk;
        }
 
+       keypad->row_shift = get_count_order(pdata->matrix_key_cols);
+
        if ((pdata->enable_rotary0 && keypad->rotary_rel_code[0] != -1) ||
            (pdata->enable_rotary1 && keypad->rotary_rel_code[1] != -1)) {
                input_dev->evbit[0] |= BIT_MASK(EV_REL);
index 55c15304ddbce997a1027e319b81e7b3fc8ba98b..4e491c1762cfe5e1ecd9bd562e8244237261aa07 100644 (file)
@@ -392,6 +392,13 @@ static const struct of_device_id tca8418_dt_ids[] = {
        { }
 };
 MODULE_DEVICE_TABLE(of, tca8418_dt_ids);
+
+/*
+ * The device tree based i2c loader looks for
+ * "i2c:" + second_component_of(property("compatible"))
+ * and therefore we need an alias to be found.
+ */
+MODULE_ALIAS("i2c:tca8418");
 #endif
 
 static struct i2c_driver tca8418_keypad_driver = {
index 52d3a9b28f0b80a253eb04584016b767c90c22cc..b36831c828d3fe7a19be14872a7eabb2b8a38ecd 100644 (file)
@@ -70,6 +70,7 @@
 #define BMA150_CFG_5_REG       0x11
 
 #define BMA150_CHIP_ID         2
+#define BMA180_CHIP_ID         3
 #define BMA150_CHIP_ID_REG     BMA150_DATA_0_REG
 
 #define BMA150_ACC_X_LSB_REG   BMA150_DATA_2_REG
@@ -539,7 +540,7 @@ static int bma150_probe(struct i2c_client *client,
        }
 
        chip_id = i2c_smbus_read_byte_data(client, BMA150_CHIP_ID_REG);
-       if (chip_id != BMA150_CHIP_ID) {
+       if (chip_id != BMA150_CHIP_ID && chip_id != BMA180_CHIP_ID) {
                dev_err(&client->dev, "BMA150 chip id error: %d\n", chip_id);
                return -EINVAL;
        }
@@ -643,6 +644,7 @@ static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL);
 
 static const struct i2c_device_id bma150_id[] = {
        { "bma150", 0 },
+       { "bma180", 0 },
        { "smb380", 0 },
        { "bma023", 0 },
        { }
index effa9c5f2c5cc6043f0ca988261b02f516c85be6..6b8441f7bc3282595feaa1378e12d871943c13c9 100644 (file)
@@ -17,7 +17,7 @@ config MOUSE_PS2
        default y
        select SERIO
        select SERIO_LIBPS2
-       select SERIO_I8042 if X86
+       select SERIO_I8042 if ARCH_MIGHT_HAVE_PC_SERIO
        select SERIO_GSCPS2 if GSC
        help
          Say Y here if you have a PS/2 mouse connected to your system. This
index 088d3541c7d3d4485380dd859e9777c6e39c94d2..b96e978a37b76a4a43ab15bf6b80e1a295a8767a 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/dmi.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/input.h>
@@ -831,7 +832,11 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
                break;
 
        case 3:
-               etd->reg_10 = 0x0b;
+               if (etd->set_hw_resolution)
+                       etd->reg_10 = 0x0b;
+               else
+                       etd->reg_10 = 0x03;
+
                if (elantech_write_reg(psmouse, 0x10, etd->reg_10))
                        rc = -1;
 
@@ -1330,6 +1335,22 @@ static int elantech_reconnect(struct psmouse *psmouse)
        return 0;
 }
 
+/*
+ * Some hw_version 3 models go into error state when we try to set bit 3 of r10
+ */
+static const struct dmi_system_id no_hw_res_dmi_table[] = {
+#if defined(CONFIG_DMI) && defined(CONFIG_X86)
+       {
+               /* Gigabyte U2442 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "U2442"),
+               },
+       },
+#endif
+       { }
+};
+
 /*
  * determine hardware version and set some properties according to it.
  */
@@ -1390,6 +1411,9 @@ static int elantech_set_properties(struct elantech_data *etd)
         */
        etd->crc_enabled = ((etd->fw_version & 0x4000) == 0x4000);
 
+       /* Enable real hardware resolution on hw_version 3 ? */
+       etd->set_hw_resolution = !dmi_check_system(no_hw_res_dmi_table);
+
        return 0;
 }
 
index 036a04abaef72314a8dcc7d444f6ab3feea377f9..9e0e2a1f340d52817fc18bf79d849bed6d340932 100644 (file)
@@ -130,6 +130,7 @@ struct elantech_data {
        bool jumpy_cursor;
        bool reports_pressure;
        bool crc_enabled;
+       bool set_hw_resolution;
        unsigned char hw_version;
        unsigned int fw_version;
        unsigned int single_finger_reports;
index ef9f4913450d12a06262dd906b8ebe93b0401dbe..c5ec703c727e11de8dd52297c0e8b7580003dab8 100644 (file)
@@ -117,6 +117,31 @@ void synaptics_reset(struct psmouse *psmouse)
 }
 
 #ifdef CONFIG_MOUSE_PS2_SYNAPTICS
+struct min_max_quirk {
+       const char * const *pnp_ids;
+       int x_min, x_max, y_min, y_max;
+};
+
+static const struct min_max_quirk min_max_pnpid_table[] = {
+       {
+               (const char * const []){"LEN0033", NULL},
+               1024, 5052, 2258, 4832
+       },
+       {
+               (const char * const []){"LEN0035", "LEN0042", NULL},
+               1232, 5710, 1156, 4696
+       },
+       {
+               (const char * const []){"LEN0034", "LEN0036", "LEN2004", NULL},
+               1024, 5112, 2024, 4832
+       },
+       {
+               (const char * const []){"LEN2001", NULL},
+               1024, 5022, 2508, 4832
+       },
+       { }
+};
+
 /* This list has been kindly provided by Synaptics. */
 static const char * const topbuttonpad_pnp_ids[] = {
        "LEN0017",
@@ -129,7 +154,7 @@ static const char * const topbuttonpad_pnp_ids[] = {
        "LEN002D",
        "LEN002E",
        "LEN0033", /* Helix */
-       "LEN0034", /* T431s, T540, X1 Carbon 2nd */
+       "LEN0034", /* T431s, L440, L540, T540, W540, X1 Carbon 2nd */
        "LEN0035", /* X240 */
        "LEN0036", /* T440 */
        "LEN0037",
@@ -142,7 +167,7 @@ static const char * const topbuttonpad_pnp_ids[] = {
        "LEN0048",
        "LEN0049",
        "LEN2000",
-       "LEN2001",
+       "LEN2001", /* Edge E431 */
        "LEN2002",
        "LEN2003",
        "LEN2004", /* L440 */
@@ -156,6 +181,18 @@ static const char * const topbuttonpad_pnp_ids[] = {
        NULL
 };
 
+static bool matches_pnp_id(struct psmouse *psmouse, const char * const ids[])
+{
+       int i;
+
+       if (!strncmp(psmouse->ps2dev.serio->firmware_id, "PNP:", 4))
+               for (i = 0; ids[i]; i++)
+                       if (strstr(psmouse->ps2dev.serio->firmware_id, ids[i]))
+                               return true;
+
+       return false;
+}
+
 /*****************************************************************************
  *     Synaptics communications functions
  ****************************************************************************/
@@ -304,20 +341,20 @@ static int synaptics_identify(struct psmouse *psmouse)
  * Resolution is left zero if touchpad does not support the query
  */
 
-static const int *quirk_min_max;
-
 static int synaptics_resolution(struct psmouse *psmouse)
 {
        struct synaptics_data *priv = psmouse->private;
        unsigned char resp[3];
+       int i;
 
-       if (quirk_min_max) {
-               priv->x_min = quirk_min_max[0];
-               priv->x_max = quirk_min_max[1];
-               priv->y_min = quirk_min_max[2];
-               priv->y_max = quirk_min_max[3];
-               return 0;
-       }
+       for (i = 0; min_max_pnpid_table[i].pnp_ids; i++)
+               if (matches_pnp_id(psmouse, min_max_pnpid_table[i].pnp_ids)) {
+                       priv->x_min = min_max_pnpid_table[i].x_min;
+                       priv->x_max = min_max_pnpid_table[i].x_max;
+                       priv->y_min = min_max_pnpid_table[i].y_min;
+                       priv->y_max = min_max_pnpid_table[i].y_max;
+                       return 0;
+               }
 
        if (SYN_ID_MAJOR(priv->identity) < 4)
                return 0;
@@ -1365,17 +1402,8 @@ static void set_input_params(struct psmouse *psmouse,
 
        if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
                __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
-               /* See if this buttonpad has a top button area */
-               if (!strncmp(psmouse->ps2dev.serio->firmware_id, "PNP:", 4)) {
-                       for (i = 0; topbuttonpad_pnp_ids[i]; i++) {
-                               if (strstr(psmouse->ps2dev.serio->firmware_id,
-                                          topbuttonpad_pnp_ids[i])) {
-                                       __set_bit(INPUT_PROP_TOPBUTTONPAD,
-                                                 dev->propbit);
-                                       break;
-                               }
-                       }
-               }
+               if (matches_pnp_id(psmouse, topbuttonpad_pnp_ids))
+                       __set_bit(INPUT_PROP_TOPBUTTONPAD, dev->propbit);
                /* Clickpads report only left button */
                __clear_bit(BTN_RIGHT, dev->keybit);
                __clear_bit(BTN_MIDDLE, dev->keybit);
@@ -1547,96 +1575,10 @@ static const struct dmi_system_id olpc_dmi_table[] __initconst = {
        { }
 };
 
-static const struct dmi_system_id min_max_dmi_table[] __initconst = {
-#if defined(CONFIG_DMI)
-       {
-               /* Lenovo ThinkPad Helix */
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Helix"),
-               },
-               .driver_data = (int []){1024, 5052, 2258, 4832},
-       },
-       {
-               /* Lenovo ThinkPad X240 */
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X240"),
-               },
-               .driver_data = (int []){1232, 5710, 1156, 4696},
-       },
-       {
-               /* Lenovo ThinkPad T431s */
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T431"),
-               },
-               .driver_data = (int []){1024, 5112, 2024, 4832},
-       },
-       {
-               /* Lenovo ThinkPad T440s */
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T440"),
-               },
-               .driver_data = (int []){1024, 5112, 2024, 4832},
-       },
-       {
-               /* Lenovo ThinkPad L440 */
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L440"),
-               },
-               .driver_data = (int []){1024, 5112, 2024, 4832},
-       },
-       {
-               /* Lenovo ThinkPad T540p */
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T540"),
-               },
-               .driver_data = (int []){1024, 5056, 2058, 4832},
-       },
-       {
-               /* Lenovo ThinkPad L540 */
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L540"),
-               },
-               .driver_data = (int []){1024, 5112, 2024, 4832},
-       },
-       {
-               /* Lenovo Yoga S1 */
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                       DMI_EXACT_MATCH(DMI_PRODUCT_VERSION,
-                                       "ThinkPad S1 Yoga"),
-               },
-               .driver_data = (int []){1232, 5710, 1156, 4696},
-       },
-       {
-               /* Lenovo ThinkPad X1 Carbon Haswell (3rd generation) */
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION,
-                                       "ThinkPad X1 Carbon 2nd"),
-               },
-               .driver_data = (int []){1024, 5112, 2024, 4832},
-       },
-#endif
-       { }
-};
-
 void __init synaptics_module_init(void)
 {
-       const struct dmi_system_id *min_max_dmi;
-
        impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table);
        broken_olpc_ec = dmi_check_system(olpc_dmi_table);
-
-       min_max_dmi = dmi_first_match(min_max_dmi_table);
-       if (min_max_dmi)
-               quirk_min_max = min_max_dmi->driver_data;
 }
 
 static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
index 762b08432de003dc155a7d78dce5572a3e352b33..8b748d99b934f4baa32674f074f8e43c153350b4 100644 (file)
@@ -79,7 +79,8 @@ static int amba_kmi_open(struct serio *io)
        writeb(divisor, KMICLKDIV);
        writeb(KMICR_EN, KMICR);
 
-       ret = request_irq(kmi->irq, amba_kmi_int, 0, "kmi-pl050", kmi);
+       ret = request_irq(kmi->irq, amba_kmi_int, IRQF_SHARED, "kmi-pl050",
+                         kmi);
        if (ret) {
                printk(KERN_ERR "kmi: failed to claim IRQ%d\n", kmi->irq);
                writeb(0, KMICR);
index 68edc9db2c6446c7534a0a5708d1b01e2c5ced98..b845e9370871bfdc0038ad8202b1d49bdddef121 100644 (file)
@@ -640,7 +640,7 @@ config TOUCHSCREEN_WM9713
 
 config TOUCHSCREEN_WM97XX_ATMEL
        tristate "WM97xx Atmel accelerated touch"
-       depends on TOUCHSCREEN_WM97XX && (AVR32 || ARCH_AT91)
+       depends on TOUCHSCREEN_WM97XX && AVR32
        help
          Say Y here for support for streaming mode with WM97xx touchscreens
          on Atmel AT91 or AVR32 systems with an AC97C module.
index c949520bd196ec47cf6e572e68cdd67c11b9f84f..57068e8035b5b2553141cb8f1a6ad27f334ea6ec 100644 (file)
@@ -3999,7 +3999,7 @@ static struct irq_remap_table *get_irq_table(u16 devid, bool ioapic)
        iommu_flush_dte(iommu, devid);
        if (devid != alias) {
                irq_lookup_table[alias] = table;
-               set_dte_irq_entry(devid, table);
+               set_dte_irq_entry(alias, table);
                iommu_flush_dte(iommu, alias);
        }
 
index b76c58dbe30ce5ac38c8422b66b5ed2ea4f0fb1e..0e08545d72989e114f016751f68df5a3191088c0 100644 (file)
@@ -788,7 +788,7 @@ static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m)
                 * per device. But we can enable the exclusion range per
                 * device. This is done here
                 */
-               set_dev_entry_bit(m->devid, DEV_ENTRY_EX);
+               set_dev_entry_bit(devid, DEV_ENTRY_EX);
                iommu->exclusion_start = m->range_start;
                iommu->exclusion_length = m->range_length;
        }
index 5208828792e603ad3f5effaa22b2e9c09ca0ac02..203b2e6a91cfca1184eb37df8761b339bc2a3728 100644 (file)
@@ -504,8 +504,10 @@ static void do_fault(struct work_struct *work)
 
        write = !!(fault->flags & PPR_FAULT_WRITE);
 
+       down_read(&fault->state->mm->mmap_sem);
        npages = get_user_pages(fault->state->task, fault->state->mm,
                                fault->address, 1, write, 0, &page, NULL);
+       up_read(&fault->state->mm->mmap_sem);
 
        if (npages == 1) {
                put_page(page);
index 51dae9167238a3ed1ff972508a02f338de6702a0..96d1df05044fb48ffceb988dd90540db9f125cdd 100644 (file)
@@ -425,7 +425,7 @@ afterXPR:
                                if (cs->debug & L1_DEB_MONITOR)
                                        debugl1(cs, "ICC %02x -> MOX1", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp - 1]);
                        }
-               AfterMOX1:
+               AfterMOX1: ;
 #endif
                }
        }
index 9380be7b18954b9308ed42abe5fafa2f87c0f76a..5f054c44b485f27dec03bb5bed4c13e95dff18db 100644 (file)
@@ -2178,6 +2178,8 @@ static int cache_create(struct cache_args *ca, struct cache **result)
        ti->num_discard_bios = 1;
        ti->discards_supported = true;
        ti->discard_zeroes_data_unsupported = true;
+       /* Discard bios must be split on a block boundary */
+       ti->split_discard_bios = true;
 
        cache->features = ca->features;
        ti->per_bio_data_size = get_per_bio_data_size(cache);
index 784695d22fde1acaaf11acd78c7263438c04648e..53b213226c015ae29cd636c033a0c088776029aa 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/crypto.h>
 #include <linux/workqueue.h>
 #include <linux/backing-dev.h>
-#include <linux/percpu.h>
 #include <linux/atomic.h>
 #include <linux/scatterlist.h>
 #include <asm/page.h>
@@ -43,6 +42,7 @@ struct convert_context {
        struct bvec_iter iter_out;
        sector_t cc_sector;
        atomic_t cc_pending;
+       struct ablkcipher_request *req;
 };
 
 /*
@@ -111,15 +111,7 @@ struct iv_tcw_private {
 enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID };
 
 /*
- * Duplicated per-CPU state for cipher.
- */
-struct crypt_cpu {
-       struct ablkcipher_request *req;
-};
-
-/*
- * The fields in here must be read only after initialization,
- * changing state should be in crypt_cpu.
+ * The fields in here must be read only after initialization.
  */
 struct crypt_config {
        struct dm_dev *dev;
@@ -150,12 +142,6 @@ struct crypt_config {
        sector_t iv_offset;
        unsigned int iv_size;
 
-       /*
-        * Duplicated per cpu state. Access through
-        * per_cpu_ptr() only.
-        */
-       struct crypt_cpu __percpu *cpu;
-
        /* ESSIV: struct crypto_cipher *essiv_tfm */
        void *iv_private;
        struct crypto_ablkcipher **tfms;
@@ -192,11 +178,6 @@ static void clone_init(struct dm_crypt_io *, struct bio *);
 static void kcryptd_queue_crypt(struct dm_crypt_io *io);
 static u8 *iv_of_dmreq(struct crypt_config *cc, struct dm_crypt_request *dmreq);
 
-static struct crypt_cpu *this_crypt_config(struct crypt_config *cc)
-{
-       return this_cpu_ptr(cc->cpu);
-}
-
 /*
  * Use this to access cipher attributes that are the same for each CPU.
  */
@@ -903,16 +884,15 @@ static void kcryptd_async_done(struct crypto_async_request *async_req,
 static void crypt_alloc_req(struct crypt_config *cc,
                            struct convert_context *ctx)
 {
-       struct crypt_cpu *this_cc = this_crypt_config(cc);
        unsigned key_index = ctx->cc_sector & (cc->tfms_count - 1);
 
-       if (!this_cc->req)
-               this_cc->req = mempool_alloc(cc->req_pool, GFP_NOIO);
+       if (!ctx->req)
+               ctx->req = mempool_alloc(cc->req_pool, GFP_NOIO);
 
-       ablkcipher_request_set_tfm(this_cc->req, cc->tfms[key_index]);
-       ablkcipher_request_set_callback(this_cc->req,
+       ablkcipher_request_set_tfm(ctx->req, cc->tfms[key_index]);
+       ablkcipher_request_set_callback(ctx->req,
            CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
-           kcryptd_async_done, dmreq_of_req(cc, this_cc->req));
+           kcryptd_async_done, dmreq_of_req(cc, ctx->req));
 }
 
 /*
@@ -921,7 +901,6 @@ static void crypt_alloc_req(struct crypt_config *cc,
 static int crypt_convert(struct crypt_config *cc,
                         struct convert_context *ctx)
 {
-       struct crypt_cpu *this_cc = this_crypt_config(cc);
        int r;
 
        atomic_set(&ctx->cc_pending, 1);
@@ -932,7 +911,7 @@ static int crypt_convert(struct crypt_config *cc,
 
                atomic_inc(&ctx->cc_pending);
 
-               r = crypt_convert_block(cc, ctx, this_cc->req);
+               r = crypt_convert_block(cc, ctx, ctx->req);
 
                switch (r) {
                /* async */
@@ -941,7 +920,7 @@ static int crypt_convert(struct crypt_config *cc,
                        reinit_completion(&ctx->restart);
                        /* fall through*/
                case -EINPROGRESS:
-                       this_cc->req = NULL;
+                       ctx->req = NULL;
                        ctx->cc_sector++;
                        continue;
 
@@ -1040,6 +1019,7 @@ static struct dm_crypt_io *crypt_io_alloc(struct crypt_config *cc,
        io->sector = sector;
        io->error = 0;
        io->base_io = NULL;
+       io->ctx.req = NULL;
        atomic_set(&io->io_pending, 0);
 
        return io;
@@ -1065,6 +1045,8 @@ static void crypt_dec_pending(struct dm_crypt_io *io)
        if (!atomic_dec_and_test(&io->io_pending))
                return;
 
+       if (io->ctx.req)
+               mempool_free(io->ctx.req, cc->req_pool);
        mempool_free(io, cc->io_pool);
 
        if (likely(!base_io))
@@ -1492,8 +1474,6 @@ static int crypt_wipe_key(struct crypt_config *cc)
 static void crypt_dtr(struct dm_target *ti)
 {
        struct crypt_config *cc = ti->private;
-       struct crypt_cpu *cpu_cc;
-       int cpu;
 
        ti->private = NULL;
 
@@ -1505,13 +1485,6 @@ static void crypt_dtr(struct dm_target *ti)
        if (cc->crypt_queue)
                destroy_workqueue(cc->crypt_queue);
 
-       if (cc->cpu)
-               for_each_possible_cpu(cpu) {
-                       cpu_cc = per_cpu_ptr(cc->cpu, cpu);
-                       if (cpu_cc->req)
-                               mempool_free(cpu_cc->req, cc->req_pool);
-               }
-
        crypt_free_tfms(cc);
 
        if (cc->bs)
@@ -1530,9 +1503,6 @@ static void crypt_dtr(struct dm_target *ti)
        if (cc->dev)
                dm_put_device(ti, cc->dev);
 
-       if (cc->cpu)
-               free_percpu(cc->cpu);
-
        kzfree(cc->cipher);
        kzfree(cc->cipher_string);
 
@@ -1588,13 +1558,6 @@ static int crypt_ctr_cipher(struct dm_target *ti,
        if (tmp)
                DMWARN("Ignoring unexpected additional cipher options");
 
-       cc->cpu = __alloc_percpu(sizeof(*(cc->cpu)),
-                                __alignof__(struct crypt_cpu));
-       if (!cc->cpu) {
-               ti->error = "Cannot allocate per cpu state";
-               goto bad_mem;
-       }
-
        /*
         * For compatibility with the original dm-crypt mapping format, if
         * only the cipher name is supplied, use cbc-plain.
index aa009e86587189a20a4ccf4734ad9d999cb5701f..ebfa411d1a7d4b0193596b515f7086639057b5d0 100644 (file)
@@ -445,11 +445,11 @@ static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path,
        else
                m->saved_queue_if_no_path = queue_if_no_path;
        m->queue_if_no_path = queue_if_no_path;
-       if (!m->queue_if_no_path)
-               dm_table_run_md_queue_async(m->ti->table);
-
        spin_unlock_irqrestore(&m->lock, flags);
 
+       if (!queue_if_no_path)
+               dm_table_run_md_queue_async(m->ti->table);
+
        return 0;
 }
 
@@ -954,7 +954,7 @@ out:
  */
 static int reinstate_path(struct pgpath *pgpath)
 {
-       int r = 0;
+       int r = 0, run_queue = 0;
        unsigned long flags;
        struct multipath *m = pgpath->pg->m;
 
@@ -978,7 +978,7 @@ static int reinstate_path(struct pgpath *pgpath)
 
        if (!m->nr_valid_paths++) {
                m->current_pgpath = NULL;
-               dm_table_run_md_queue_async(m->ti->table);
+               run_queue = 1;
        } else if (m->hw_handler_name && (m->current_pg == pgpath->pg)) {
                if (queue_work(kmpath_handlerd, &pgpath->activate_path.work))
                        m->pg_init_in_progress++;
@@ -991,6 +991,8 @@ static int reinstate_path(struct pgpath *pgpath)
 
 out:
        spin_unlock_irqrestore(&m->lock, flags);
+       if (run_queue)
+               dm_table_run_md_queue_async(m->ti->table);
 
        return r;
 }
index 13abade76ad9bbd65c83c67d35f075506b17b63f..242ac2ea5f295c0bf2ad2db85fdd86812936851d 100644 (file)
@@ -27,6 +27,9 @@
 #define MAPPING_POOL_SIZE 1024
 #define PRISON_CELLS 1024
 #define COMMIT_PERIOD HZ
+#define NO_SPACE_TIMEOUT_SECS 60
+
+static unsigned no_space_timeout_secs = NO_SPACE_TIMEOUT_SECS;
 
 DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(snapshot_copy_throttle,
                "A percentage of time allocated for copy on write");
@@ -175,6 +178,7 @@ struct pool {
        struct workqueue_struct *wq;
        struct work_struct worker;
        struct delayed_work waker;
+       struct delayed_work no_space_timeout;
 
        unsigned long last_commit_jiffies;
        unsigned ref_count;
@@ -935,7 +939,7 @@ static int commit(struct pool *pool)
 {
        int r;
 
-       if (get_pool_mode(pool) != PM_WRITE)
+       if (get_pool_mode(pool) >= PM_READ_ONLY)
                return -EINVAL;
 
        r = dm_pool_commit_metadata(pool->pmd);
@@ -1590,6 +1594,20 @@ static void do_waker(struct work_struct *ws)
        queue_delayed_work(pool->wq, &pool->waker, COMMIT_PERIOD);
 }
 
+/*
+ * We're holding onto IO to allow userland time to react.  After the
+ * timeout either the pool will have been resized (and thus back in
+ * PM_WRITE mode), or we degrade to PM_READ_ONLY and start erroring IO.
+ */
+static void do_no_space_timeout(struct work_struct *ws)
+{
+       struct pool *pool = container_of(to_delayed_work(ws), struct pool,
+                                        no_space_timeout);
+
+       if (get_pool_mode(pool) == PM_OUT_OF_DATA_SPACE && !pool->pf.error_if_no_space)
+               set_pool_mode(pool, PM_READ_ONLY);
+}
+
 /*----------------------------------------------------------------*/
 
 struct noflush_work {
@@ -1654,6 +1672,7 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
        struct pool_c *pt = pool->ti->private;
        bool needs_check = dm_pool_metadata_needs_check(pool->pmd);
        enum pool_mode old_mode = get_pool_mode(pool);
+       unsigned long no_space_timeout = ACCESS_ONCE(no_space_timeout_secs) * HZ;
 
        /*
         * Never allow the pool to transition to PM_WRITE mode if user
@@ -1715,6 +1734,9 @@ static void set_pool_mode(struct pool *pool, enum pool_mode new_mode)
                pool->process_discard = process_discard;
                pool->process_prepared_mapping = process_prepared_mapping;
                pool->process_prepared_discard = process_prepared_discard_passdown;
+
+               if (!pool->pf.error_if_no_space && no_space_timeout)
+                       queue_delayed_work(pool->wq, &pool->no_space_timeout, no_space_timeout);
                break;
 
        case PM_WRITE:
@@ -2100,6 +2122,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
 
        INIT_WORK(&pool->worker, do_worker);
        INIT_DELAYED_WORK(&pool->waker, do_waker);
+       INIT_DELAYED_WORK(&pool->no_space_timeout, do_no_space_timeout);
        spin_lock_init(&pool->lock);
        bio_list_init(&pool->deferred_flush_bios);
        INIT_LIST_HEAD(&pool->prepared_mappings);
@@ -2662,6 +2685,7 @@ static void pool_postsuspend(struct dm_target *ti)
        struct pool *pool = pt->pool;
 
        cancel_delayed_work(&pool->waker);
+       cancel_delayed_work(&pool->no_space_timeout);
        flush_workqueue(pool->wq);
        (void) commit(pool);
 }
@@ -3487,6 +3511,9 @@ static void dm_thin_exit(void)
 module_init(dm_thin_init);
 module_exit(dm_thin_exit);
 
+module_param_named(no_space_timeout, no_space_timeout_secs, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(no_space_timeout, "Out of data space queue IO timeout in seconds");
+
 MODULE_DESCRIPTION(DM_NAME " thin provisioning target");
 MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
 MODULE_LICENSE("GPL");
index 8fda38d23e3847aa4d96ecd147e996514a5a4af7..237b7e0ddc7ae2617af41cb1fb9dc0cc195f44ab 100644 (file)
@@ -8516,7 +8516,8 @@ static int md_notify_reboot(struct notifier_block *this,
                if (mddev_trylock(mddev)) {
                        if (mddev->pers)
                                __md_stop_writes(mddev);
-                       mddev->safemode = 2;
+                       if (mddev->persistent)
+                               mddev->safemode = 2;
                        mddev_unlock(mddev);
                }
                need_delay = 1;
index 33fc408e5eacef0a1dce55fd5c0d578fc244b663..cb882aae9e20d4f7032a400884f45f50de57528f 100644 (file)
@@ -1172,6 +1172,13 @@ static void __make_request(struct mddev *mddev, struct bio *bio)
        int max_sectors;
        int sectors;
 
+       /*
+        * Register the new request and wait if the reconstruction
+        * thread has put up a bar for new requests.
+        * Continue immediately if no resync is active currently.
+        */
+       wait_barrier(conf);
+
        sectors = bio_sectors(bio);
        while (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
            bio->bi_iter.bi_sector < conf->reshape_progress &&
@@ -1552,12 +1559,6 @@ static void make_request(struct mddev *mddev, struct bio *bio)
 
        md_write_start(mddev, bio);
 
-       /*
-        * Register the new request and wait if the reconstruction
-        * thread has put up a bar for new requests.
-        * Continue immediately if no resync is active currently.
-        */
-       wait_barrier(conf);
 
        do {
 
index e8a1ce204036f45cca1d1d495f29c8c7b72942d5..cdd7c1b7259b008e873cc711294a3f0cecba422a 100644 (file)
@@ -1109,7 +1109,7 @@ static int ov7670_enum_framesizes(struct v4l2_subdev *sd,
         * windows that fall outside that.
         */
        for (i = 0; i < n_win_sizes; i++) {
-               struct ov7670_win_size *win = &info->devtype->win_sizes[index];
+               struct ov7670_win_size *win = &info->devtype->win_sizes[i];
                if (info->min_width && win->width < info->min_width)
                        continue;
                if (info->min_height && win->height < info->min_height)
index a4459301b5f829efcae8563241ef1108933194d7..ee0f57e01b5677df58c9f74565767bcaf57d54af 100644 (file)
@@ -1616,7 +1616,7 @@ static int s5c73m3_get_platform_data(struct s5c73m3 *state)
        if (ret < 0)
                return -EINVAL;
 
-       node_ep = v4l2_of_get_next_endpoint(node, NULL);
+       node_ep = of_graph_get_next_endpoint(node, NULL);
        if (!node_ep) {
                dev_warn(dev, "no endpoint defined for node: %s\n",
                                                node->full_name);
index d5a7a135f75d39d5bc2f6fb3366639dd6dc7ee34..703560fa5e73b456cbc0951ccb61957bdfecebac 100644 (file)
@@ -93,6 +93,7 @@ static long media_device_enum_entities(struct media_device *mdev,
        struct media_entity *ent;
        struct media_entity_desc u_ent;
 
+       memset(&u_ent, 0, sizeof(u_ent));
        if (copy_from_user(&u_ent.id, &uent->id, sizeof(u_ent.id)))
                return -EFAULT;
 
index b4f12d00be059c3f381b31295d435074ee291dab..65670825296209917cc33546d1d43abb60af5ed5 100644 (file)
@@ -372,18 +372,32 @@ static int vpbe_stop_streaming(struct vb2_queue *vq)
 {
        struct vpbe_fh *fh = vb2_get_drv_priv(vq);
        struct vpbe_layer *layer = fh->layer;
+       struct vpbe_display *disp = fh->disp_dev;
+       unsigned long flags;
 
        if (!vb2_is_streaming(vq))
                return 0;
 
        /* release all active buffers */
+       spin_lock_irqsave(&disp->dma_queue_lock, flags);
+       if (layer->cur_frm == layer->next_frm) {
+               vb2_buffer_done(&layer->cur_frm->vb, VB2_BUF_STATE_ERROR);
+       } else {
+               if (layer->cur_frm != NULL)
+                       vb2_buffer_done(&layer->cur_frm->vb,
+                                       VB2_BUF_STATE_ERROR);
+               if (layer->next_frm != NULL)
+                       vb2_buffer_done(&layer->next_frm->vb,
+                                       VB2_BUF_STATE_ERROR);
+       }
+
        while (!list_empty(&layer->dma_queue)) {
                layer->next_frm = list_entry(layer->dma_queue.next,
                                                struct vpbe_disp_buffer, list);
                list_del(&layer->next_frm->list);
                vb2_buffer_done(&layer->next_frm->vb, VB2_BUF_STATE_ERROR);
        }
-
+       spin_unlock_irqrestore(&disp->dma_queue_lock, flags);
        return 0;
 }
 
index d762246eabf5a3b78a8c348e7a5e5f149580e143..0379cb9f9a9c25c7b0a4efb52e741d4723ddcdc4 100644 (file)
@@ -734,6 +734,8 @@ static int vpfe_release(struct file *file)
                }
                vpfe_dev->io_usrs = 0;
                vpfe_dev->numbuffers = config_params.numbuffers;
+               videobuf_stop(&vpfe_dev->buffer_queue);
+               videobuf_mmap_free(&vpfe_dev->buffer_queue);
        }
 
        /* Decrement device usrs counter */
index 756da78bac23109dbd3e7da464243da381354231..8dea0b84a3ad66788ab29b2437303ebd3bc38d6f 100644 (file)
@@ -358,8 +358,31 @@ static int vpif_stop_streaming(struct vb2_queue *vq)
 
        common = &ch->common[VPIF_VIDEO_INDEX];
 
+       /* Disable channel as per its device type and channel id */
+       if (VPIF_CHANNEL0_VIDEO == ch->channel_id) {
+               enable_channel0(0);
+               channel0_intr_enable(0);
+       }
+       if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) ||
+               (2 == common->started)) {
+               enable_channel1(0);
+               channel1_intr_enable(0);
+       }
+       common->started = 0;
+
        /* release all active buffers */
        spin_lock_irqsave(&common->irqlock, flags);
+       if (common->cur_frm == common->next_frm) {
+               vb2_buffer_done(&common->cur_frm->vb, VB2_BUF_STATE_ERROR);
+       } else {
+               if (common->cur_frm != NULL)
+                       vb2_buffer_done(&common->cur_frm->vb,
+                                       VB2_BUF_STATE_ERROR);
+               if (common->next_frm != NULL)
+                       vb2_buffer_done(&common->next_frm->vb,
+                                       VB2_BUF_STATE_ERROR);
+       }
+
        while (!list_empty(&common->dma_queue)) {
                common->next_frm = list_entry(common->dma_queue.next,
                                                struct vpif_cap_buffer, list);
@@ -933,17 +956,6 @@ static int vpif_release(struct file *filep)
        if (fh->io_allowed[VPIF_VIDEO_INDEX]) {
                /* Reset io_usrs member of channel object */
                common->io_usrs = 0;
-               /* Disable channel as per its device type and channel id */
-               if (VPIF_CHANNEL0_VIDEO == ch->channel_id) {
-                       enable_channel0(0);
-                       channel0_intr_enable(0);
-               }
-               if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) ||
-                   (2 == common->started)) {
-                       enable_channel1(0);
-                       channel1_intr_enable(0);
-               }
-               common->started = 0;
                /* Free buffers allocated */
                vb2_queue_release(&common->buffer_queue);
                vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
index 0ac841e35aa48dd59bdf17b32f97afbe94b561b5..aed41edd050102e89248cecbb2607a4f45e6eb12 100644 (file)
@@ -320,8 +320,31 @@ static int vpif_stop_streaming(struct vb2_queue *vq)
 
        common = &ch->common[VPIF_VIDEO_INDEX];
 
+       /* Disable channel */
+       if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {
+               enable_channel2(0);
+               channel2_intr_enable(0);
+       }
+       if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) ||
+               (2 == common->started)) {
+               enable_channel3(0);
+               channel3_intr_enable(0);
+       }
+       common->started = 0;
+
        /* release all active buffers */
        spin_lock_irqsave(&common->irqlock, flags);
+       if (common->cur_frm == common->next_frm) {
+               vb2_buffer_done(&common->cur_frm->vb, VB2_BUF_STATE_ERROR);
+       } else {
+               if (common->cur_frm != NULL)
+                       vb2_buffer_done(&common->cur_frm->vb,
+                                       VB2_BUF_STATE_ERROR);
+               if (common->next_frm != NULL)
+                       vb2_buffer_done(&common->next_frm->vb,
+                                       VB2_BUF_STATE_ERROR);
+       }
+
        while (!list_empty(&common->dma_queue)) {
                common->next_frm = list_entry(common->dma_queue.next,
                                                struct vpif_disp_buffer, list);
@@ -773,18 +796,6 @@ static int vpif_release(struct file *filep)
        if (fh->io_allowed[VPIF_VIDEO_INDEX]) {
                /* Reset io_usrs member of channel object */
                common->io_usrs = 0;
-               /* Disable channel */
-               if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {
-                       enable_channel2(0);
-                       channel2_intr_enable(0);
-               }
-               if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) ||
-                   (2 == common->started)) {
-                       enable_channel3(0);
-                       channel3_intr_enable(0);
-               }
-               common->started = 0;
-
                /* Free buffers allocated */
                vb2_queue_release(&common->buffer_queue);
                vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
index da2fc86cc52433bd8f1c6b32a898baa87c2a1064..25dbf5b05a96186527cf520f568f03721b181a80 100644 (file)
@@ -122,7 +122,7 @@ static struct fimc_fmt fimc_formats[] = {
        }, {
                .name           = "YUV 4:2:2 planar, Y/Cb/Cr",
                .fourcc         = V4L2_PIX_FMT_YUV422P,
-               .depth          = { 12 },
+               .depth          = { 16 },
                .color          = FIMC_FMT_YCBYCR422,
                .memplanes      = 1,
                .colplanes      = 3,
index 3aecaf4650942429eba75ee89cc33180aac4ae07..f0c9c42867de2e8cad570229f8592a6b445f1b47 100644 (file)
@@ -195,7 +195,7 @@ static int fc2580_set_params(struct dvb_frontend *fe)
 
        f_ref = 2UL * priv->cfg->clock / r_val;
        n_val = div_u64_rem(f_vco, f_ref, &k_val);
-       k_val_reg = 1UL * k_val * (1 << 20) / f_ref;
+       k_val_reg = div_u64(1ULL * k_val * (1 << 20), f_ref);
 
        ret = fc2580_wr_reg(priv, 0x18, r18_val | ((k_val_reg >> 16) & 0xff));
        if (ret < 0)
@@ -348,8 +348,8 @@ static int fc2580_set_params(struct dvb_frontend *fe)
        if (ret < 0)
                goto err;
 
-       ret = fc2580_wr_reg(priv, 0x37, 1UL * priv->cfg->clock * \
-                       fc2580_if_filter_lut[i].mul / 1000000000);
+       ret = fc2580_wr_reg(priv, 0x37, div_u64(1ULL * priv->cfg->clock *
+                       fc2580_if_filter_lut[i].mul, 1000000000));
        if (ret < 0)
                goto err;
 
index be38a9e637e08d20f673cb0c8de85fea608442d8..646c994521361ba7579466d814a8e7d2422397b5 100644 (file)
@@ -22,6 +22,7 @@
 #define FC2580_PRIV_H
 
 #include "fc2580.h"
+#include <linux/math64.h>
 
 struct fc2580_reg_val {
        u8 reg;
index 7407b8338ccfa33ce6a4179e5b9e99632a3f6ebf..bc38f03394cda0e1a397b390f354b620fe486a73 100644 (file)
@@ -41,4 +41,3 @@ ccflags-y += -I$(srctree)/drivers/media/dvb-core
 ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
 ccflags-y += -I$(srctree)/drivers/media/tuners
 ccflags-y += -I$(srctree)/drivers/media/common
-ccflags-y += -I$(srctree)/drivers/staging/media/rtl2832u_sdr
index 61d196e8b3abde6dc0d97e26fe3ca7cae9292957..dcbd392e6efc8f38265d8b7fd805c4b38eff9410 100644 (file)
@@ -24,7 +24,6 @@
 
 #include "rtl2830.h"
 #include "rtl2832.h"
-#include "rtl2832_sdr.h"
 
 #include "qt1010.h"
 #include "mt2060.h"
 #include "tua9001.h"
 #include "r820t.h"
 
+/*
+ * RTL2832_SDR module is in staging. That logic is added in order to avoid any
+ * hard dependency to drivers/staging/ directory as we want compile mainline
+ * driver even whole staging directory is missing.
+ */
+#include <media/v4l2-subdev.h>
+
+#if IS_ENABLED(CONFIG_DVB_RTL2832_SDR)
+struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
+       struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
+       struct v4l2_subdev *sd);
+#else
+static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
+       struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
+       struct v4l2_subdev *sd)
+{
+       return NULL;
+}
+#endif
+
+#ifdef CONFIG_MEDIA_ATTACH
+#define dvb_attach_sdr(FUNCTION, ARGS...) ({ \
+       void *__r = NULL; \
+       typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
+       if (__a) { \
+               __r = (void *) __a(ARGS); \
+               if (__r == NULL) \
+                       symbol_put(FUNCTION); \
+       } \
+       __r; \
+})
+
+#else
+#define dvb_attach_sdr(FUNCTION, ARGS...) ({ \
+       FUNCTION(ARGS); \
+})
+
+#endif
+
 static int rtl28xxu_disable_rc;
 module_param_named(disable_rc, rtl28xxu_disable_rc, int, 0644);
 MODULE_PARM_DESC(disable_rc, "disable RTL2832U remote controller");
@@ -908,7 +946,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
                                adap->fe[0]->ops.tuner_ops.get_rf_strength;
 
                /* attach SDR */
-               dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
+               dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
                                &rtl28xxu_rtl2832_fc0012_config, NULL);
                break;
        case TUNER_RTL2832_FC0013:
@@ -920,7 +958,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
                                adap->fe[0]->ops.tuner_ops.get_rf_strength;
 
                /* attach SDR */
-               dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
+               dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
                                &rtl28xxu_rtl2832_fc0013_config, NULL);
                break;
        case TUNER_RTL2832_E4000: {
@@ -951,7 +989,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
                        i2c_set_adapdata(i2c_adap_internal, d);
 
                        /* attach SDR */
-                       dvb_attach(rtl2832_sdr_attach, adap->fe[0],
+                       dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0],
                                        i2c_adap_internal,
                                        &rtl28xxu_rtl2832_e4000_config, sd);
                }
@@ -982,7 +1020,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
                                adap->fe[0]->ops.tuner_ops.get_rf_strength;
 
                /* attach SDR */
-               dvb_attach(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
+               dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
                                &rtl28xxu_rtl2832_r820t_config, NULL);
                break;
        case TUNER_RTL2832_R828D:
index 7277dbd2afcdb8c88629aafc2c9013b38cd79390..ecbcb39feb71ad21f7b765c36ac20858234d01f6 100644 (file)
@@ -1430,10 +1430,8 @@ static const struct usb_device_id device_table[] = {
        {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
        {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
        {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
-#if !IS_ENABLED(CONFIG_USB_SN9C102)
        {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
        {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
-#endif
        {USB_DEVICE(0x0c45, 0x6027), SB(OV7630, 101)}, /* Genius Eye 310 */
        {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
        {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
index 04b2daf567bec232d384337491543151d890c69a..7e2411c36419c394b3d23a81eb5bdd4b5fee88c2 100644 (file)
@@ -178,6 +178,9 @@ struct v4l2_create_buffers32 {
 
 static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
 {
+       if (get_user(kp->type, &up->type))
+               return -EFAULT;
+
        switch (kp->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
@@ -204,17 +207,16 @@ static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
 
 static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
 {
-       if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
-                       get_user(kp->type, &up->type))
-                       return -EFAULT;
+       if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)))
+               return -EFAULT;
        return __get_v4l2_format32(kp, up);
 }
 
 static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
 {
        if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
-           copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format.fmt)))
-                       return -EFAULT;
+           copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format)))
+               return -EFAULT;
        return __get_v4l2_format32(&kp->format, &up->format);
 }
 
index 110c03627051cb749ef92d853e47322714b1dd51..b59a17fb7c3e3f3eff43faecac3610f58df1dbd8 100644 (file)
@@ -108,8 +108,19 @@ static int devbus_set_timing_params(struct devbus *devbus,
                        node->full_name);
                return err;
        }
-       /* Convert bit width to byte width */
-       r.bus_width /= 8;
+
+       /*
+        * The bus width is encoded into the register as 0 for 8 bits,
+        * and 1 for 16 bits, so we do the necessary conversion here.
+        */
+       if (r.bus_width == 8)
+               r.bus_width = 0;
+       else if (r.bus_width == 16)
+               r.bus_width = 1;
+       else {
+               dev_err(devbus->dev, "invalid bus width %d\n", r.bus_width);
+               return -EINVAL;
+       }
 
        err = get_timing_param_ps(devbus, node, "devbus,badr-skew-ps",
                                 &r.badr_skew);
index c9de3d598ea515279ff0f79f1214984b041266db..1d15735f9ef930ed18e384b1c63b7deb1fd42981 100644 (file)
@@ -338,28 +338,58 @@ int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
                int num_sg, bool read, int timeout)
 {
        struct completion trans_done;
-       int err = 0, count;
+       u8 dir;
+       int err = 0, i, count;
        long timeleft;
        unsigned long flags;
+       struct scatterlist *sg;
+       enum dma_data_direction dma_dir;
+       u32 val;
+       dma_addr_t addr;
+       unsigned int len;
+
+       dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg);
+
+       /* don't transfer data during abort processing */
+       if (pcr->remove_pci)
+               return -EINVAL;
+
+       if ((sglist == NULL) || (num_sg <= 0))
+               return -EINVAL;
 
-       count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read);
+       if (read) {
+               dir = DEVICE_TO_HOST;
+               dma_dir = DMA_FROM_DEVICE;
+       } else {
+               dir = HOST_TO_DEVICE;
+               dma_dir = DMA_TO_DEVICE;
+       }
+
+       count = dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
        if (count < 1) {
                dev_err(&(pcr->pci->dev), "scatterlist map failed\n");
                return -EINVAL;
        }
        dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count);
 
+       val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE;
+       pcr->sgi = 0;
+       for_each_sg(sglist, sg, count, i) {
+               addr = sg_dma_address(sg);
+               len = sg_dma_len(sg);
+               rtsx_pci_add_sg_tbl(pcr, addr, len, i == count - 1);
+       }
 
        spin_lock_irqsave(&pcr->lock, flags);
 
        pcr->done = &trans_done;
        pcr->trans_result = TRANS_NOT_READY;
        init_completion(&trans_done);
+       rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr);
+       rtsx_pci_writel(pcr, RTSX_HDBCTLR, val);
 
        spin_unlock_irqrestore(&pcr->lock, flags);
 
-       rtsx_pci_dma_transfer(pcr, sglist, count, read);
-
        timeleft = wait_for_completion_interruptible_timeout(
                        &trans_done, msecs_to_jiffies(timeout));
        if (timeleft <= 0) {
@@ -383,7 +413,7 @@ out:
        pcr->done = NULL;
        spin_unlock_irqrestore(&pcr->lock, flags);
 
-       rtsx_pci_dma_unmap_sg(pcr, sglist, num_sg, read);
+       dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir);
 
        if ((err < 0) && (err != -ENODEV))
                rtsx_pci_stop_cmd(pcr);
@@ -395,73 +425,6 @@ out:
 }
 EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data);
 
-int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
-               int num_sg, bool read)
-{
-       enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-
-       if (pcr->remove_pci)
-               return -EINVAL;
-
-       if ((sglist == NULL) || num_sg < 1)
-               return -EINVAL;
-
-       return dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dir);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_dma_map_sg);
-
-int rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
-               int num_sg, bool read)
-{
-       enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-
-       if (pcr->remove_pci)
-               return -EINVAL;
-
-       if (sglist == NULL || num_sg < 1)
-               return -EINVAL;
-
-       dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dir);
-       return num_sg;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_dma_unmap_sg);
-
-int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist,
-               int sg_count, bool read)
-{
-       struct scatterlist *sg;
-       dma_addr_t addr;
-       unsigned int len;
-       int i;
-       u32 val;
-       u8 dir = read ? DEVICE_TO_HOST : HOST_TO_DEVICE;
-       unsigned long flags;
-
-       if (pcr->remove_pci)
-               return -EINVAL;
-
-       if ((sglist == NULL) || (sg_count < 1))
-               return -EINVAL;
-
-       val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE;
-       pcr->sgi = 0;
-       for_each_sg(sglist, sg, sg_count, i) {
-               addr = sg_dma_address(sg);
-               len = sg_dma_len(sg);
-               rtsx_pci_add_sg_tbl(pcr, addr, len, i == sg_count - 1);
-       }
-
-       spin_lock_irqsave(&pcr->lock, flags);
-
-       rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr);
-       rtsx_pci_writel(pcr, RTSX_HDBCTLR, val);
-
-       spin_unlock_irqrestore(&pcr->lock, flags);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_dma_transfer);
-
 int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len)
 {
        int err;
@@ -873,8 +836,6 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
        int_reg = rtsx_pci_readl(pcr, RTSX_BIPR);
        /* Clear interrupt flag */
        rtsx_pci_writel(pcr, RTSX_BIPR, int_reg);
-       dev_dbg(&pcr->pci->dev, "=========== BIPR 0x%8x ==========\n", int_reg);
-
        if ((int_reg & pcr->bier) == 0) {
                spin_unlock(&pcr->lock);
                return IRQ_NONE;
@@ -905,28 +866,17 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
        }
 
        if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) {
-               if (int_reg & (TRANS_FAIL_INT | DELINK_INT))
+               if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) {
                        pcr->trans_result = TRANS_RESULT_FAIL;
-               else if (int_reg & TRANS_OK_INT)
+                       if (pcr->done)
+                               complete(pcr->done);
+               } else if (int_reg & TRANS_OK_INT) {
                        pcr->trans_result = TRANS_RESULT_OK;
-
-               if (pcr->done)
-                       complete(pcr->done);
-
-               if (int_reg & SD_EXIST) {
-                       struct rtsx_slot *slot = &pcr->slots[RTSX_SD_CARD];
-                       if (slot && slot->done_transfer)
-                               slot->done_transfer(slot->p_dev);
-               }
-
-               if (int_reg & MS_EXIST) {
-                       struct rtsx_slot *slot = &pcr->slots[RTSX_SD_CARD];
-                       if (slot && slot->done_transfer)
-                               slot->done_transfer(slot->p_dev);
+                       if (pcr->done)
+                               complete(pcr->done);
                }
        }
 
-
        if (pcr->card_inserted || pcr->card_removed)
                schedule_delayed_work(&pcr->carddet_work,
                                msecs_to_jiffies(200));
index 5fb994f9a653570d75f2b3deb6aab32129d17503..0b9ded13a3ae89d72a94e7e8e075f62496483f0e 100644 (file)
 #include <linux/mfd/rtsx_pci.h>
 #include <asm/unaligned.h>
 
-struct realtek_next {
-       unsigned int    sg_count;
-       s32             cookie;
-};
-
 struct realtek_pci_sdmmc {
        struct platform_device  *pdev;
        struct rtsx_pcr         *pcr;
        struct mmc_host         *mmc;
        struct mmc_request      *mrq;
-       struct mmc_command      *cmd;
-       struct mmc_data         *data;
-
-       spinlock_t              lock;
-       struct timer_list       timer;
-       struct tasklet_struct   cmd_tasklet;
-       struct tasklet_struct   data_tasklet;
-       struct tasklet_struct   finish_tasklet;
-
-       u8                      rsp_type;
-       u8                      rsp_len;
-       int                     sg_count;
+
+       struct mutex            host_mutex;
+
        u8                      ssc_depth;
        unsigned int            clock;
        bool                    vpclk;
@@ -62,13 +48,8 @@ struct realtek_pci_sdmmc {
        int                     power_state;
 #define SDMMC_POWER_ON         1
 #define SDMMC_POWER_OFF                0
-
-       struct realtek_next     next_data;
 };
 
-static int sd_start_multi_rw(struct realtek_pci_sdmmc *host,
-               struct mmc_request *mrq);
-
 static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host)
 {
        return &(host->pdev->dev);
@@ -105,95 +86,6 @@ static void sd_print_debug_regs(struct realtek_pci_sdmmc *host)
 #define sd_print_debug_regs(host)
 #endif /* DEBUG */
 
-static void sd_isr_done_transfer(struct platform_device *pdev)
-{
-       struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev);
-
-       spin_lock(&host->lock);
-       if (host->cmd)
-               tasklet_schedule(&host->cmd_tasklet);
-       if (host->data)
-               tasklet_schedule(&host->data_tasklet);
-       spin_unlock(&host->lock);
-}
-
-static void sd_request_timeout(unsigned long host_addr)
-{
-       struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr;
-       unsigned long flags;
-
-       spin_lock_irqsave(&host->lock, flags);
-
-       if (!host->mrq) {
-               dev_err(sdmmc_dev(host), "error: no request exist\n");
-               goto out;
-       }
-
-       if (host->cmd)
-               host->cmd->error = -ETIMEDOUT;
-       if (host->data)
-               host->data->error = -ETIMEDOUT;
-
-       dev_dbg(sdmmc_dev(host), "timeout for request\n");
-
-out:
-       tasklet_schedule(&host->finish_tasklet);
-       spin_unlock_irqrestore(&host->lock, flags);
-}
-
-static void sd_finish_request(unsigned long host_addr)
-{
-       struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr;
-       struct rtsx_pcr *pcr = host->pcr;
-       struct mmc_request *mrq;
-       struct mmc_command *cmd;
-       struct mmc_data *data;
-       unsigned long flags;
-       bool any_error;
-
-       spin_lock_irqsave(&host->lock, flags);
-
-       del_timer(&host->timer);
-       mrq = host->mrq;
-       if (!mrq) {
-               dev_err(sdmmc_dev(host), "error: no request need finish\n");
-               goto out;
-       }
-
-       cmd = mrq->cmd;
-       data = mrq->data;
-
-       any_error = (mrq->sbc && mrq->sbc->error) ||
-               (mrq->stop && mrq->stop->error) ||
-               (cmd && cmd->error) || (data && data->error);
-
-       if (any_error) {
-               rtsx_pci_stop_cmd(pcr);
-               sd_clear_error(host);
-       }
-
-       if (data) {
-               if (any_error)
-                       data->bytes_xfered = 0;
-               else
-                       data->bytes_xfered = data->blocks * data->blksz;
-
-               if (!data->host_cookie)
-                       rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len,
-                                       data->flags & MMC_DATA_READ);
-
-       }
-
-       host->mrq = NULL;
-       host->cmd = NULL;
-       host->data = NULL;
-
-out:
-       spin_unlock_irqrestore(&host->lock, flags);
-       mutex_unlock(&pcr->pcr_mutex);
-       mmc_request_done(host->mmc, mrq);
-}
-
 static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt,
                u8 *buf, int buf_len, int timeout)
 {
@@ -311,7 +203,8 @@ static int sd_write_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt,
        return 0;
 }
 
-static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd)
+static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host,
+               struct mmc_command *cmd)
 {
        struct rtsx_pcr *pcr = host->pcr;
        u8 cmd_idx = (u8)cmd->opcode;
@@ -319,14 +212,11 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd)
        int err = 0;
        int timeout = 100;
        int i;
+       u8 *ptr;
+       int stat_idx = 0;
        u8 rsp_type;
        int rsp_len = 5;
-       unsigned long flags;
-
-       if (host->cmd)
-               dev_err(sdmmc_dev(host), "error: cmd already exist\n");
-
-       host->cmd = cmd;
+       bool clock_toggled = false;
 
        dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n",
                        __func__, cmd_idx, arg);
@@ -361,8 +251,6 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd)
                err = -EINVAL;
                goto out;
        }
-       host->rsp_type = rsp_type;
-       host->rsp_len = rsp_len;
 
        if (rsp_type == SD_RSP_TYPE_R1b)
                timeout = 3000;
@@ -372,6 +260,8 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd)
                                0xFF, SD_CLK_TOGGLE_EN);
                if (err < 0)
                        goto out;
+
+               clock_toggled = true;
        }
 
        rtsx_pci_init_cmd(pcr);
@@ -395,60 +285,25 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd)
                /* Read data from ping-pong buffer */
                for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++)
                        rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0);
+               stat_idx = 16;
        } else if (rsp_type != SD_RSP_TYPE_R0) {
                /* Read data from SD_CMDx registers */
                for (i = SD_CMD0; i <= SD_CMD4; i++)
                        rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0);
+               stat_idx = 5;
        }
 
        rtsx_pci_add_cmd(pcr, READ_REG_CMD, SD_STAT1, 0, 0);
 
-       mod_timer(&host->timer, jiffies + msecs_to_jiffies(timeout));
-
-       spin_lock_irqsave(&pcr->lock, flags);
-       pcr->trans_result = TRANS_NOT_READY;
-       rtsx_pci_send_cmd_no_wait(pcr);
-       spin_unlock_irqrestore(&pcr->lock, flags);
-
-       return;
-
-out:
-       cmd->error = err;
-       tasklet_schedule(&host->finish_tasklet);
-}
-
-static void sd_get_rsp(unsigned long host_addr)
-{
-       struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr;
-       struct rtsx_pcr *pcr = host->pcr;
-       struct mmc_command *cmd;
-       int i, err = 0, stat_idx;
-       u8 *ptr, rsp_type;
-       unsigned long flags;
-
-       spin_lock_irqsave(&host->lock, flags);
-
-       cmd = host->cmd;
-       host->cmd = NULL;
-
-       if (!cmd) {
-               dev_err(sdmmc_dev(host), "error: cmd not exist\n");
+       err = rtsx_pci_send_cmd(pcr, timeout);
+       if (err < 0) {
+               sd_print_debug_regs(host);
+               sd_clear_error(host);
+               dev_dbg(sdmmc_dev(host),
+                       "rtsx_pci_send_cmd error (err = %d)\n", err);
                goto out;
        }
 
-       spin_lock(&pcr->lock);
-       if (pcr->trans_result == TRANS_NO_DEVICE)
-               err = -ENODEV;
-       else if (pcr->trans_result != TRANS_RESULT_OK)
-               err = -EINVAL;
-       spin_unlock(&pcr->lock);
-
-       if (err < 0)
-               goto out;
-
-       rsp_type = host->rsp_type;
-       stat_idx = host->rsp_len;
-
        if (rsp_type == SD_RSP_TYPE_R0) {
                err = 0;
                goto out;
@@ -485,106 +340,26 @@ static void sd_get_rsp(unsigned long host_addr)
                                cmd->resp[0]);
        }
 
-       if (cmd == host->mrq->sbc) {
-               sd_send_cmd(host, host->mrq->cmd);
-               spin_unlock_irqrestore(&host->lock, flags);
-               return;
-       }
-
-       if (cmd == host->mrq->stop)
-               goto out;
-
-       if (cmd->data) {
-               sd_start_multi_rw(host, host->mrq);
-               spin_unlock_irqrestore(&host->lock, flags);
-               return;
-       }
-
 out:
        cmd->error = err;
 
-       tasklet_schedule(&host->finish_tasklet);
-       spin_unlock_irqrestore(&host->lock, flags);
-}
-
-static int sd_pre_dma_transfer(struct realtek_pci_sdmmc *host,
-                       struct mmc_data *data, struct realtek_next *next)
-{
-       struct rtsx_pcr *pcr = host->pcr;
-       int read = data->flags & MMC_DATA_READ;
-       int sg_count = 0;
-
-       if (!next && data->host_cookie &&
-               data->host_cookie != host->next_data.cookie) {
-               dev_err(sdmmc_dev(host),
-                       "error: invalid cookie data[%d] host[%d]\n",
-                       data->host_cookie, host->next_data.cookie);
-               data->host_cookie = 0;
-       }
-
-       if (next || (!next && data->host_cookie != host->next_data.cookie))
-               sg_count = rtsx_pci_dma_map_sg(pcr,
-                               data->sg, data->sg_len, read);
-       else
-               sg_count = host->next_data.sg_count;
-
-       if (next) {
-               next->sg_count = sg_count;
-               if (++next->cookie < 0)
-                       next->cookie = 1;
-               data->host_cookie = next->cookie;
-       }
-
-       return sg_count;
-}
-
-static void sdmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
-               bool is_first_req)
-{
-       struct realtek_pci_sdmmc *host = mmc_priv(mmc);
-       struct mmc_data *data = mrq->data;
-
-       if (data->host_cookie) {
-               dev_err(sdmmc_dev(host),
-                       "error: descard already cookie data[%d]\n",
-                       data->host_cookie);
-               data->host_cookie = 0;
-       }
-
-       dev_dbg(sdmmc_dev(host), "dma sg prepared: %d\n",
-               sd_pre_dma_transfer(host, data, &host->next_data));
-}
-
-static void sdmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
-               int err)
-{
-       struct realtek_pci_sdmmc *host = mmc_priv(mmc);
-       struct rtsx_pcr *pcr = host->pcr;
-       struct mmc_data *data = mrq->data;
-       int read = data->flags & MMC_DATA_READ;
-
-       rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len, read);
-       data->host_cookie = 0;
+       if (err && clock_toggled)
+               rtsx_pci_write_register(pcr, SD_BUS_STAT,
+                               SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
 }
 
-static int sd_start_multi_rw(struct realtek_pci_sdmmc *host,
-               struct mmc_request *mrq)
+static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq)
 {
        struct rtsx_pcr *pcr = host->pcr;
        struct mmc_host *mmc = host->mmc;
        struct mmc_card *card = mmc->card;
        struct mmc_data *data = mrq->data;
        int uhs = mmc_card_uhs(card);
-       int read = data->flags & MMC_DATA_READ;
+       int read = (data->flags & MMC_DATA_READ) ? 1 : 0;
        u8 cfg2, trans_mode;
        int err;
        size_t data_len = data->blksz * data->blocks;
 
-       if (host->data)
-               dev_err(sdmmc_dev(host), "error: data already exist\n");
-
-       host->data = data;
-
        if (read) {
                cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 |
                        SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0;
@@ -635,54 +410,15 @@ static int sd_start_multi_rw(struct realtek_pci_sdmmc *host,
        rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER,
                        SD_TRANSFER_END, SD_TRANSFER_END);
 
-       mod_timer(&host->timer, jiffies + 10 * HZ);
        rtsx_pci_send_cmd_no_wait(pcr);
 
-       err = rtsx_pci_dma_transfer(pcr, data->sg, host->sg_count, read);
-       if (err < 0) {
-               data->error = err;
-               tasklet_schedule(&host->finish_tasklet);
-       }
-       return 0;
-}
-
-static void sd_finish_multi_rw(unsigned long host_addr)
-{
-       struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr;
-       struct rtsx_pcr *pcr = host->pcr;
-       struct mmc_data *data;
-       int err = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&host->lock, flags);
-
-       if (!host->data) {
-               dev_err(sdmmc_dev(host), "error: no data exist\n");
-               goto out;
-       }
-
-       data = host->data;
-       host->data = NULL;
-
-       if (pcr->trans_result == TRANS_NO_DEVICE)
-               err = -ENODEV;
-       else if (pcr->trans_result != TRANS_RESULT_OK)
-               err = -EINVAL;
-
+       err = rtsx_pci_transfer_data(pcr, data->sg, data->sg_len, read, 10000);
        if (err < 0) {
-               data->error = err;
-               goto out;
-       }
-
-       if (!host->mrq->sbc && data->stop) {
-               sd_send_cmd(host, data->stop);
-               spin_unlock_irqrestore(&host->lock, flags);
-               return;
+               sd_clear_error(host);
+               return err;
        }
 
-out:
-       tasklet_schedule(&host->finish_tasklet);
-       spin_unlock_irqrestore(&host->lock, flags);
+       return 0;
 }
 
 static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host)
@@ -901,13 +637,6 @@ static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode)
        return 0;
 }
 
-static inline bool sd_use_muti_rw(struct mmc_command *cmd)
-{
-       return mmc_op_multi(cmd->opcode) ||
-               (cmd->opcode == MMC_READ_SINGLE_BLOCK) ||
-               (cmd->opcode == MMC_WRITE_BLOCK);
-}
-
 static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
        struct realtek_pci_sdmmc *host = mmc_priv(mmc);
@@ -916,14 +645,6 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
        struct mmc_data *data = mrq->data;
        unsigned int data_size = 0;
        int err;
-       unsigned long flags;
-
-       mutex_lock(&pcr->pcr_mutex);
-       spin_lock_irqsave(&host->lock, flags);
-
-       if (host->mrq)
-               dev_err(sdmmc_dev(host), "error: request already exist\n");
-       host->mrq = mrq;
 
        if (host->eject) {
                cmd->error = -ENOMEDIUM;
@@ -936,6 +657,8 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
                goto finish;
        }
 
+       mutex_lock(&pcr->pcr_mutex);
+
        rtsx_pci_start_run(pcr);
 
        rtsx_pci_switch_clock(pcr, host->clock, host->ssc_depth,
@@ -944,28 +667,46 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
        rtsx_pci_write_register(pcr, CARD_SHARE_MODE,
                        CARD_SHARE_MASK, CARD_SHARE_48_SD);
 
+       mutex_lock(&host->host_mutex);
+       host->mrq = mrq;
+       mutex_unlock(&host->host_mutex);
+
        if (mrq->data)
                data_size = data->blocks * data->blksz;
 
-       if (sd_use_muti_rw(cmd))
-               host->sg_count = sd_pre_dma_transfer(host, data, NULL);
+       if (!data_size || mmc_op_multi(cmd->opcode) ||
+                       (cmd->opcode == MMC_READ_SINGLE_BLOCK) ||
+                       (cmd->opcode == MMC_WRITE_BLOCK)) {
+               sd_send_cmd_get_rsp(host, cmd);
 
-       if (!data_size || sd_use_muti_rw(cmd)) {
-               if (mrq->sbc)
-                       sd_send_cmd(host, mrq->sbc);
-               else
-                       sd_send_cmd(host, cmd);
-               spin_unlock_irqrestore(&host->lock, flags);
+               if (!cmd->error && data_size) {
+                       sd_rw_multi(host, mrq);
+
+                       if (mmc_op_multi(cmd->opcode) && mrq->stop)
+                               sd_send_cmd_get_rsp(host, mrq->stop);
+               }
        } else {
-               spin_unlock_irqrestore(&host->lock, flags);
                sd_normal_rw(host, mrq);
-               tasklet_schedule(&host->finish_tasklet);
        }
-       return;
+
+       if (mrq->data) {
+               if (cmd->error || data->error)
+                       data->bytes_xfered = 0;
+               else
+                       data->bytes_xfered = data->blocks * data->blksz;
+       }
+
+       mutex_unlock(&pcr->pcr_mutex);
 
 finish:
-       tasklet_schedule(&host->finish_tasklet);
-       spin_unlock_irqrestore(&host->lock, flags);
+       if (cmd->error)
+               dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error);
+
+       mutex_lock(&host->host_mutex);
+       host->mrq = NULL;
+       mutex_unlock(&host->host_mutex);
+
+       mmc_request_done(mmc, mrq);
 }
 
 static int sd_set_bus_width(struct realtek_pci_sdmmc *host,
@@ -1400,8 +1141,6 @@ out:
 }
 
 static const struct mmc_host_ops realtek_pci_sdmmc_ops = {
-       .pre_req = sdmmc_pre_req,
-       .post_req = sdmmc_post_req,
        .request = sdmmc_request,
        .set_ios = sdmmc_set_ios,
        .get_ro = sdmmc_get_ro,
@@ -1465,7 +1204,6 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
        struct realtek_pci_sdmmc *host;
        struct rtsx_pcr *pcr;
        struct pcr_handle *handle = pdev->dev.platform_data;
-       unsigned long host_addr;
 
        if (!handle)
                return -ENXIO;
@@ -1489,15 +1227,8 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
        pcr->slots[RTSX_SD_CARD].p_dev = pdev;
        pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event;
 
-       host_addr = (unsigned long)host;
-       host->next_data.cookie = 1;
-       setup_timer(&host->timer, sd_request_timeout, host_addr);
-       tasklet_init(&host->cmd_tasklet, sd_get_rsp, host_addr);
-       tasklet_init(&host->data_tasklet, sd_finish_multi_rw, host_addr);
-       tasklet_init(&host->finish_tasklet, sd_finish_request, host_addr);
-       spin_lock_init(&host->lock);
+       mutex_init(&host->host_mutex);
 
-       pcr->slots[RTSX_SD_CARD].done_transfer = sd_isr_done_transfer;
        realtek_init_host(host);
 
        mmc_add_host(mmc);
@@ -1510,8 +1241,6 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
        struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev);
        struct rtsx_pcr *pcr;
        struct mmc_host *mmc;
-       struct mmc_request *mrq;
-       unsigned long flags;
 
        if (!host)
                return 0;
@@ -1519,33 +1248,22 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
        pcr = host->pcr;
        pcr->slots[RTSX_SD_CARD].p_dev = NULL;
        pcr->slots[RTSX_SD_CARD].card_event = NULL;
-       pcr->slots[RTSX_SD_CARD].done_transfer = NULL;
        mmc = host->mmc;
-       mrq = host->mrq;
 
-       spin_lock_irqsave(&host->lock, flags);
+       mutex_lock(&host->host_mutex);
        if (host->mrq) {
                dev_dbg(&(pdev->dev),
                        "%s: Controller removed during transfer\n",
                        mmc_hostname(mmc));
 
-               if (mrq->sbc)
-                       mrq->sbc->error = -ENOMEDIUM;
-               if (mrq->cmd)
-                       mrq->cmd->error = -ENOMEDIUM;
-               if (mrq->stop)
-                       mrq->stop->error = -ENOMEDIUM;
-               if (mrq->data)
-                       mrq->data->error = -ENOMEDIUM;
+               rtsx_pci_complete_unfinished_transfer(pcr);
 
-               tasklet_schedule(&host->finish_tasklet);
+               host->mrq->cmd->error = -ENOMEDIUM;
+               if (host->mrq->stop)
+                       host->mrq->stop->error = -ENOMEDIUM;
+               mmc_request_done(mmc, host->mrq);
        }
-       spin_unlock_irqrestore(&host->lock, flags);
-
-       del_timer_sync(&host->timer);
-       tasklet_kill(&host->cmd_tasklet);
-       tasklet_kill(&host->data_tasklet);
-       tasklet_kill(&host->finish_tasklet);
+       mutex_unlock(&host->host_mutex);
 
        mmc_remove_host(mmc);
        host->eject = true;
index 4615d79fc93f795c869687117744e01653219478..b922c8efcf4012376548c15e4a3af50562d47095 100644 (file)
@@ -523,6 +523,7 @@ static struct nand_ecclayout hwecc4_2048 = {
 #if defined(CONFIG_OF)
 static const struct of_device_id davinci_nand_of_match[] = {
        {.compatible = "ti,davinci-nand", },
+       {.compatible = "ti,keystone-nand", },
        {},
 };
 MODULE_DEVICE_TABLE(of, davinci_nand_of_match);
@@ -581,6 +582,11 @@ static struct davinci_nand_pdata
                    of_property_read_bool(pdev->dev.of_node,
                        "ti,davinci-nand-use-bbt"))
                        pdata->bbt_options = NAND_BBT_USE_FLASH;
+
+               if (of_device_is_compatible(pdev->dev.of_node,
+                                           "ti,keystone-nand")) {
+                       pdata->options |= NAND_NO_SUBPAGE_WRITE;
+               }
        }
 
        return dev_get_platdata(&pdev->dev);
index 7ff473c871a9a249bd02007c2176ec5c471d7626..8d659e6a1b4c0899e32706b8bfa7fe3270ff715a 100644 (file)
@@ -431,7 +431,7 @@ int ubiblock_create(struct ubi_volume_info *vi)
         * Create one workqueue per volume (per registered block device).
         * Rembember workqueues are cheap, they're not threads.
         */
-       dev->wq = alloc_workqueue(gd->disk_name, 0, 0);
+       dev->wq = alloc_workqueue("%s", 0, 0, gd->disk_name);
        if (!dev->wq)
                goto out_free_queue;
        INIT_WORK(&dev->work, ubiblock_do_work);
index 02317c1c02385914c94175fa8757089c677e2b94..0f3425dac91046300f93587d4f341e080c98e322 100644 (file)
@@ -671,6 +671,8 @@ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi)
 
        e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF);
        self_check_in_wl_tree(ubi, e, &ubi->free);
+       ubi->free_count--;
+       ubi_assert(ubi->free_count >= 0);
        rb_erase(&e->u.rb, &ubi->free);
 
        return e;
@@ -684,6 +686,9 @@ int ubi_wl_get_peb(struct ubi_device *ubi)
        peb = __wl_get_peb(ubi);
        spin_unlock(&ubi->wl_lock);
 
+       if (peb < 0)
+               return peb;
+
        err = ubi_self_check_all_ff(ubi, peb, ubi->vid_hdr_aloffset,
                                    ubi->peb_size - ubi->vid_hdr_aloffset);
        if (err) {
@@ -1068,6 +1073,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
 
                        /* Give the unused PEB back */
                        wl_tree_add(e2, &ubi->free);
+                       ubi->free_count++;
                        goto out_cancel;
                }
                self_check_in_wl_tree(ubi, e1, &ubi->used);
index 9f69e818b0009db7881b3f8c862393836e5a604b..93580a47cc548851a36d1ff4cb45e88636565a3e 100644 (file)
@@ -82,7 +82,8 @@ static inline struct arp_pkt *arp_pkt(const struct sk_buff *skb)
 }
 
 /* Forward declaration */
-static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]);
+static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
+                                     bool strict_match);
 static void rlb_purge_src_ip(struct bonding *bond, struct arp_pkt *arp);
 static void rlb_src_unlink(struct bonding *bond, u32 index);
 static void rlb_src_link(struct bonding *bond, u32 ip_src_hash,
@@ -459,7 +460,7 @@ static void rlb_teach_disabled_mac_on_primary(struct bonding *bond, u8 addr[])
 
        bond->alb_info.rlb_promisc_timeout_counter = 0;
 
-       alb_send_learning_packets(bond->curr_active_slave, addr);
+       alb_send_learning_packets(bond->curr_active_slave, addr, true);
 }
 
 /* slave being removed should not be active at this point
@@ -995,7 +996,7 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
 /*********************** tlb/rlb shared functions *********************/
 
 static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[],
-                           u16 vid)
+                           __be16 vlan_proto, u16 vid)
 {
        struct learning_pkt pkt;
        struct sk_buff *skb;
@@ -1021,7 +1022,7 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[],
        skb->dev = slave->dev;
 
        if (vid) {
-               skb = vlan_put_tag(skb, htons(ETH_P_8021Q), vid);
+               skb = vlan_put_tag(skb, vlan_proto, vid);
                if (!skb) {
                        pr_err("%s: Error: failed to insert VLAN tag\n",
                               slave->bond->dev->name);
@@ -1032,22 +1033,32 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[],
        dev_queue_xmit(skb);
 }
 
-
-static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
+static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
+                                     bool strict_match)
 {
        struct bonding *bond = bond_get_bond_by_slave(slave);
        struct net_device *upper;
        struct list_head *iter;
 
        /* send untagged */
-       alb_send_lp_vid(slave, mac_addr, 0);
+       alb_send_lp_vid(slave, mac_addr, 0, 0);
 
        /* loop through vlans and send one packet for each */
        rcu_read_lock();
        netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
-               if (upper->priv_flags & IFF_802_1Q_VLAN)
-                       alb_send_lp_vid(slave, mac_addr,
-                                       vlan_dev_vlan_id(upper));
+               if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) {
+                       if (strict_match &&
+                           ether_addr_equal_64bits(mac_addr,
+                                                   upper->dev_addr)) {
+                               alb_send_lp_vid(slave, mac_addr,
+                                               vlan_dev_vlan_proto(upper),
+                                               vlan_dev_vlan_id(upper));
+                       } else if (!strict_match) {
+                               alb_send_lp_vid(slave, upper->dev_addr,
+                                               vlan_dev_vlan_proto(upper),
+                                               vlan_dev_vlan_id(upper));
+                       }
+               }
        }
        rcu_read_unlock();
 }
@@ -1107,7 +1118,7 @@ static void alb_fasten_mac_swap(struct bonding *bond, struct slave *slave1,
 
        /* fasten the change in the switch */
        if (SLAVE_IS_OK(slave1)) {
-               alb_send_learning_packets(slave1, slave1->dev->dev_addr);
+               alb_send_learning_packets(slave1, slave1->dev->dev_addr, false);
                if (bond->alb_info.rlb_enabled) {
                        /* inform the clients that the mac address
                         * has changed
@@ -1119,7 +1130,7 @@ static void alb_fasten_mac_swap(struct bonding *bond, struct slave *slave1,
        }
 
        if (SLAVE_IS_OK(slave2)) {
-               alb_send_learning_packets(slave2, slave2->dev->dev_addr);
+               alb_send_learning_packets(slave2, slave2->dev->dev_addr, false);
                if (bond->alb_info.rlb_enabled) {
                        /* inform the clients that the mac address
                         * has changed
@@ -1490,6 +1501,8 @@ void bond_alb_monitor(struct work_struct *work)
 
        /* send learning packets */
        if (bond_info->lp_counter >= BOND_ALB_LP_TICKS(bond)) {
+               bool strict_match;
+
                /* 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
@@ -1497,8 +1510,15 @@ void bond_alb_monitor(struct work_struct *work)
                 */
                read_lock(&bond->curr_slave_lock);
 
-               bond_for_each_slave_rcu(bond, slave, iter)
-                       alb_send_learning_packets(slave, slave->dev->dev_addr);
+               bond_for_each_slave_rcu(bond, slave, iter) {
+                       /* If updating current_active, use all currently
+                        * user mac addreses (!strict_match).  Otherwise, only
+                        * use mac of the slave device.
+                        */
+                       strict_match = (slave != bond->curr_active_slave);
+                       alb_send_learning_packets(slave, slave->dev->dev_addr,
+                                                 strict_match);
+               }
 
                read_unlock(&bond->curr_slave_lock);
 
@@ -1721,7 +1741,8 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
        } else {
                /* set the new_slave to the bond mac address */
                alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr);
-               alb_send_learning_packets(new_slave, bond->dev->dev_addr);
+               alb_send_learning_packets(new_slave, bond->dev->dev_addr,
+                                         false);
        }
 
        write_lock_bh(&bond->curr_slave_lock);
@@ -1764,7 +1785,8 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
                alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr);
 
                read_lock(&bond->lock);
-               alb_send_learning_packets(bond->curr_active_slave, bond_dev->dev_addr);
+               alb_send_learning_packets(bond->curr_active_slave,
+                                         bond_dev->dev_addr, false);
                if (bond->alb_info.rlb_enabled) {
                        /* inform clients mac address has changed */
                        rlb_req_update_slave_clients(bond, bond->curr_active_slave);
index 69aff72c895716fe6c579d2bf7f46c79ddca2a36..d3a67896d43541f0b8ebc0b4e193db945087bc56 100644 (file)
@@ -2126,10 +2126,10 @@ static bool bond_has_this_ip(struct bonding *bond, __be32 ip)
  */
 static void bond_arp_send(struct net_device *slave_dev, int arp_op,
                          __be32 dest_ip, __be32 src_ip,
-                         struct bond_vlan_tag *inner,
-                         struct bond_vlan_tag *outer)
+                         struct bond_vlan_tag *tags)
 {
        struct sk_buff *skb;
+       int i;
 
        pr_debug("arp %d on slave %s: dst %pI4 src %pI4\n",
                 arp_op, slave_dev->name, &dest_ip, &src_ip);
@@ -2141,21 +2141,26 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op,
                net_err_ratelimited("ARP packet allocation failed\n");
                return;
        }
-       if (outer->vlan_id) {
-               if (inner->vlan_id) {
-                       pr_debug("inner tag: proto %X vid %X\n",
-                                ntohs(inner->vlan_proto), inner->vlan_id);
-                       skb = __vlan_put_tag(skb, inner->vlan_proto,
-                                            inner->vlan_id);
-                       if (!skb) {
-                               net_err_ratelimited("failed to insert inner VLAN tag\n");
-                               return;
-                       }
-               }
 
-               pr_debug("outer reg: proto %X vid %X\n",
-                        ntohs(outer->vlan_proto), outer->vlan_id);
-               skb = vlan_put_tag(skb, outer->vlan_proto, outer->vlan_id);
+       /* Go through all the tags backwards and add them to the packet */
+       for (i = BOND_MAX_VLAN_ENCAP - 1; i > 0; i--) {
+               if (!tags[i].vlan_id)
+                       continue;
+
+               pr_debug("inner tag: proto %X vid %X\n",
+                        ntohs(tags[i].vlan_proto), tags[i].vlan_id);
+               skb = __vlan_put_tag(skb, tags[i].vlan_proto,
+                                    tags[i].vlan_id);
+               if (!skb) {
+                       net_err_ratelimited("failed to insert inner VLAN tag\n");
+                       return;
+               }
+       }
+       /* Set the outer tag */
+       if (tags[0].vlan_id) {
+               pr_debug("outer tag: proto %X vid %X\n",
+                        ntohs(tags[0].vlan_proto), tags[0].vlan_id);
+               skb = vlan_put_tag(skb, tags[0].vlan_proto, tags[0].vlan_id);
                if (!skb) {
                        net_err_ratelimited("failed to insert outer VLAN tag\n");
                        return;
@@ -2164,22 +2169,52 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op,
        arp_xmit(skb);
 }
 
+/* Validate the device path between the @start_dev and the @end_dev.
+ * The path is valid if the @end_dev is reachable through device
+ * stacking.
+ * When the path is validated, collect any vlan information in the
+ * path.
+ */
+static bool bond_verify_device_path(struct net_device *start_dev,
+                                   struct net_device *end_dev,
+                                   struct bond_vlan_tag *tags)
+{
+       struct net_device *upper;
+       struct list_head  *iter;
+       int  idx;
+
+       if (start_dev == end_dev)
+               return true;
+
+       netdev_for_each_upper_dev_rcu(start_dev, upper, iter) {
+               if (bond_verify_device_path(upper, end_dev, tags)) {
+                       if (is_vlan_dev(upper)) {
+                               idx = vlan_get_encap_level(upper);
+                               if (idx >= BOND_MAX_VLAN_ENCAP)
+                                       return false;
+
+                               tags[idx].vlan_proto =
+                                                   vlan_dev_vlan_proto(upper);
+                               tags[idx].vlan_id = vlan_dev_vlan_id(upper);
+                       }
+                       return true;
+               }
+       }
+
+       return false;
+}
 
 static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
 {
-       struct net_device *upper, *vlan_upper;
-       struct list_head *iter, *vlan_iter;
        struct rtable *rt;
-       struct bond_vlan_tag inner, outer;
+       struct bond_vlan_tag tags[BOND_MAX_VLAN_ENCAP];
        __be32 *targets = bond->params.arp_targets, addr;
        int i;
+       bool ret;
 
        for (i = 0; i < BOND_MAX_ARP_TARGETS && targets[i]; i++) {
                pr_debug("basa: target %pI4\n", &targets[i]);
-               inner.vlan_proto = 0;
-               inner.vlan_id = 0;
-               outer.vlan_proto = 0;
-               outer.vlan_id = 0;
+               memset(tags, 0, sizeof(tags));
 
                /* Find out through which dev should the packet go */
                rt = ip_route_output(dev_net(bond->dev), targets[i], 0,
@@ -2192,7 +2227,8 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
                                net_warn_ratelimited("%s: no route to arp_ip_target %pI4 and arp_validate is set\n",
                                                     bond->dev->name,
                                                     &targets[i]);
-                       bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], 0, &inner, &outer);
+                       bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
+                                     0, tags);
                        continue;
                }
 
@@ -2201,52 +2237,12 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
                        goto found;
 
                rcu_read_lock();
-               /* first we search only for vlan devices. for every vlan
-                * found we verify its upper dev list, searching for the
-                * rt->dst.dev. If found we save the tag of the vlan and
-                * proceed to send the packet.
-                */
-               netdev_for_each_all_upper_dev_rcu(bond->dev, vlan_upper,
-                                                 vlan_iter) {
-                       if (!is_vlan_dev(vlan_upper))
-                               continue;
-
-                       if (vlan_upper == rt->dst.dev) {
-                               outer.vlan_proto = vlan_dev_vlan_proto(vlan_upper);
-                               outer.vlan_id = vlan_dev_vlan_id(vlan_upper);
-                               rcu_read_unlock();
-                               goto found;
-                       }
-                       netdev_for_each_all_upper_dev_rcu(vlan_upper, upper,
-                                                         iter) {
-                               if (upper == rt->dst.dev) {
-                                       /* If the upper dev is a vlan dev too,
-                                        *  set the vlan tag to inner tag.
-                                        */
-                                       if (is_vlan_dev(upper)) {
-                                               inner.vlan_proto = vlan_dev_vlan_proto(upper);
-                                               inner.vlan_id = vlan_dev_vlan_id(upper);
-                                       }
-                                       outer.vlan_proto = vlan_dev_vlan_proto(vlan_upper);
-                                       outer.vlan_id = vlan_dev_vlan_id(vlan_upper);
-                                       rcu_read_unlock();
-                                       goto found;
-                               }
-                       }
-               }
-
-               /* if the device we're looking for is not on top of any of
-                * our upper vlans, then just search for any dev that
-                * matches, and in case it's a vlan - save the id
-                */
-               netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
-                       if (upper == rt->dst.dev) {
-                               rcu_read_unlock();
-                               goto found;
-                       }
-               }
+               ret = bond_verify_device_path(bond->dev, rt->dst.dev, tags);
                rcu_read_unlock();
 
+               if (ret)
+                       goto found;
+
                /* Not our device - skip */
                pr_debug("%s: no path to arp_ip_target %pI4 via rt.dev %s\n",
                         bond->dev->name, &targets[i],
@@ -2259,7 +2255,7 @@ found:
                addr = bond_confirm_addr(rt->dst.dev, targets[i], 0);
                ip_rt_put(rt);
                bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
-                             addr, &inner, &outer);
+                             addr, tags);
        }
 }
 
index 724e30fa20b9fa70166b5d9b25ed9029fab6db73..832070298446458483cdf1132cc46b63ba323a7d 100644 (file)
@@ -125,6 +125,7 @@ static const struct bond_opt_value bond_fail_over_mac_tbl[] = {
 static const struct bond_opt_value bond_intmax_tbl[] = {
        { "off",     0,       BOND_VALFLAG_DEFAULT},
        { "maxval",  INT_MAX, BOND_VALFLAG_MAX},
+       { NULL,      -1,      0}
 };
 
 static const struct bond_opt_value bond_lacp_rate_tbl[] = {
index 0e8b268da0a08f58c4443c6c36aa62bb9ef0f071..5f6babcfc26e6aa56881ef2dc24b1ed51e3d7539 100644 (file)
@@ -534,7 +534,7 @@ static ssize_t bonding_show_min_links(struct device *d,
 {
        struct bonding *bond = to_bond(d);
 
-       return sprintf(buf, "%d\n", bond->params.min_links);
+       return sprintf(buf, "%u\n", bond->params.min_links);
 }
 
 static ssize_t bonding_store_min_links(struct device *d,
index b8bdd0acc8f334ac97bca2ddfea602f473c3272f..00bea320e3b50c1eaa75a712f7afbbe65ac146fb 100644 (file)
@@ -36,6 +36,7 @@
 
 #define bond_version DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n"
 
+#define BOND_MAX_VLAN_ENCAP    2
 #define BOND_MAX_ARP_TARGETS   16
 
 #define BOND_DEFAULT_MIIMON    100
index a5c8dcfa83579376a36105c8c055e63f792c42ad..95e04e2002daec774d394d0f0912ca7e952f280f 100644 (file)
@@ -60,6 +60,8 @@
 #define CONTROL_IE             BIT(1)
 #define CONTROL_INIT           BIT(0)
 
+#define CONTROL_IRQMSK         (CONTROL_EIE | CONTROL_IE | CONTROL_SIE)
+
 /* test register */
 #define TEST_RX                        BIT(7)
 #define TEST_TX1               BIT(6)
 #define IF_COMM_CONTROL                BIT(4)
 #define IF_COMM_CLR_INT_PND    BIT(3)
 #define IF_COMM_TXRQST         BIT(2)
+#define IF_COMM_CLR_NEWDAT     IF_COMM_TXRQST
 #define IF_COMM_DATAA          BIT(1)
 #define IF_COMM_DATAB          BIT(0)
-#define IF_COMM_ALL            (IF_COMM_MASK | IF_COMM_ARB | \
-                               IF_COMM_CONTROL | IF_COMM_TXRQST | \
-                               IF_COMM_DATAA | IF_COMM_DATAB)
+
+/* TX buffer setup */
+#define IF_COMM_TX             (IF_COMM_ARB | IF_COMM_CONTROL | \
+                                IF_COMM_TXRQST |                \
+                                IF_COMM_DATAA | IF_COMM_DATAB)
 
 /* For the low buffers we clear the interrupt bit, but keep newdat */
 #define IF_COMM_RCV_LOW                (IF_COMM_MASK | IF_COMM_ARB | \
                                 IF_COMM_DATAA | IF_COMM_DATAB)
 
 /* For the high buffers we clear the interrupt bit and newdat */
-#define IF_COMM_RCV_HIGH       (IF_COMM_RCV_LOW | IF_COMM_TXRQST)
+#define IF_COMM_RCV_HIGH       (IF_COMM_RCV_LOW | IF_COMM_CLR_NEWDAT)
+
+
+/* Receive setup of message objects */
+#define IF_COMM_RCV_SETUP      (IF_COMM_MASK | IF_COMM_ARB | IF_COMM_CONTROL)
+
+/* Invalidation of message objects */
+#define IF_COMM_INVAL          (IF_COMM_ARB | IF_COMM_CONTROL)
 
 /* IFx arbitration */
-#define IF_ARB_MSGVAL          BIT(15)
-#define IF_ARB_MSGXTD          BIT(14)
-#define IF_ARB_TRANSMIT                BIT(13)
+#define IF_ARB_MSGVAL          BIT(31)
+#define IF_ARB_MSGXTD          BIT(30)
+#define IF_ARB_TRANSMIT                BIT(29)
 
 /* IFx message control */
 #define IF_MCONT_NEWDAT                BIT(15)
 #define IF_MCONT_EOB           BIT(7)
 #define IF_MCONT_DLC_MASK      0xf
 
+#define IF_MCONT_RCV           (IF_MCONT_RXIE | IF_MCONT_UMASK)
+#define IF_MCONT_RCV_EOB       (IF_MCONT_RCV | IF_MCONT_EOB)
+
+#define IF_MCONT_TX            (IF_MCONT_TXIE | IF_MCONT_EOB)
+
 /*
  * Use IF1 for RX and IF2 for TX
  */
 #define IF_RX                  0
 #define IF_TX                  1
 
-/* status interrupt */
-#define STATUS_INTERRUPT       0x8000
-
-/* global interrupt masks */
-#define ENABLE_ALL_INTERRUPTS  1
-#define DISABLE_ALL_INTERRUPTS 0
-
 /* minimum timeout for checking BUSY status */
 #define MIN_TIMEOUT_VALUE      6
 
@@ -171,6 +181,7 @@ enum c_can_lec_type {
        LEC_BIT0_ERROR,
        LEC_CRC_ERROR,
        LEC_UNUSED,
+       LEC_MASK = LEC_UNUSED,
 };
 
 /*
@@ -226,143 +237,115 @@ static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable)
                priv->raminit(priv, enable);
 }
 
-static inline int get_tx_next_msg_obj(const struct c_can_priv *priv)
-{
-       return (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) +
-                       C_CAN_MSG_OBJ_TX_FIRST;
-}
-
-static inline int get_tx_echo_msg_obj(int txecho)
-{
-       return (txecho & C_CAN_NEXT_MSG_OBJ_MASK) + C_CAN_MSG_OBJ_TX_FIRST;
-}
-
-static u32 c_can_read_reg32(struct c_can_priv *priv, enum reg index)
-{
-       u32 val = priv->read_reg(priv, index);
-       val |= ((u32) priv->read_reg(priv, index + 1)) << 16;
-       return val;
-}
-
-static void c_can_enable_all_interrupts(struct c_can_priv *priv,
-                                               int enable)
+static void c_can_irq_control(struct c_can_priv *priv, bool enable)
 {
-       unsigned int cntrl_save = priv->read_reg(priv,
-                                               C_CAN_CTRL_REG);
+       u32 ctrl = priv->read_reg(priv, C_CAN_CTRL_REG) & ~CONTROL_IRQMSK;
 
        if (enable)
-               cntrl_save |= (CONTROL_SIE | CONTROL_EIE | CONTROL_IE);
-       else
-               cntrl_save &= ~(CONTROL_EIE | CONTROL_IE | CONTROL_SIE);
+               ctrl |= CONTROL_IRQMSK;
 
-       priv->write_reg(priv, C_CAN_CTRL_REG, cntrl_save);
+       priv->write_reg(priv, C_CAN_CTRL_REG, ctrl);
 }
 
-static inline int c_can_msg_obj_is_busy(struct c_can_priv *priv, int iface)
+static void c_can_obj_update(struct net_device *dev, int iface, u32 cmd, u32 obj)
 {
-       int count = MIN_TIMEOUT_VALUE;
+       struct c_can_priv *priv = netdev_priv(dev);
+       int cnt, reg = C_CAN_IFACE(COMREQ_REG, iface);
 
-       while (count && priv->read_reg(priv,
-                               C_CAN_IFACE(COMREQ_REG, iface)) &
-                               IF_COMR_BUSY) {
-               count--;
+       priv->write_reg(priv, reg + 1, cmd);
+       priv->write_reg(priv, reg, obj);
+
+       for (cnt = MIN_TIMEOUT_VALUE; cnt; cnt--) {
+               if (!(priv->read_reg(priv, reg) & IF_COMR_BUSY))
+                       return;
                udelay(1);
        }
+       netdev_err(dev, "Updating object timed out\n");
 
-       if (!count)
-               return 1;
+}
 
-       return 0;
+static inline void c_can_object_get(struct net_device *dev, int iface,
+                                   u32 obj, u32 cmd)
+{
+       c_can_obj_update(dev, iface, cmd, obj);
 }
 
-static inline void c_can_object_get(struct net_device *dev,
-                                       int iface, int objno, int mask)
+static inline void c_can_object_put(struct net_device *dev, int iface,
+                                   u32 obj, u32 cmd)
 {
-       struct c_can_priv *priv = netdev_priv(dev);
+       c_can_obj_update(dev, iface, cmd | IF_COMM_WR, obj);
+}
 
-       /*
-        * As per specs, after writting the message object number in the
-        * IF command request register the transfer b/w interface
-        * register and message RAM must be complete in 6 CAN-CLK
-        * period.
-        */
-       priv->write_reg(priv, C_CAN_IFACE(COMMSK_REG, iface),
-                       IFX_WRITE_LOW_16BIT(mask));
-       priv->write_reg(priv, C_CAN_IFACE(COMREQ_REG, iface),
-                       IFX_WRITE_LOW_16BIT(objno));
+/*
+ * Note: According to documentation clearing TXIE while MSGVAL is set
+ * is not allowed, but works nicely on C/DCAN. And that lowers the I/O
+ * load significantly.
+ */
+static void c_can_inval_tx_object(struct net_device *dev, int iface, int obj)
+{
+       struct c_can_priv *priv = netdev_priv(dev);
 
-       if (c_can_msg_obj_is_busy(priv, iface))
-               netdev_err(dev, "timed out in object get\n");
+       priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0);
+       c_can_object_put(dev, iface, obj, IF_COMM_INVAL);
 }
 
-static inline void c_can_object_put(struct net_device *dev,
-                                       int iface, int objno, int mask)
+static void c_can_inval_msg_object(struct net_device *dev, int iface, int obj)
 {
        struct c_can_priv *priv = netdev_priv(dev);
 
-       /*
-        * As per specs, after writting the message object number in the
-        * IF command request register the transfer b/w interface
-        * register and message RAM must be complete in 6 CAN-CLK
-        * period.
-        */
-       priv->write_reg(priv, C_CAN_IFACE(COMMSK_REG, iface),
-                       (IF_COMM_WR | IFX_WRITE_LOW_16BIT(mask)));
-       priv->write_reg(priv, C_CAN_IFACE(COMREQ_REG, iface),
-                       IFX_WRITE_LOW_16BIT(objno));
-
-       if (c_can_msg_obj_is_busy(priv, iface))
-               netdev_err(dev, "timed out in object put\n");
+       priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), 0);
+       priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), 0);
+       c_can_inval_tx_object(dev, iface, obj);
 }
 
-static void c_can_write_msg_object(struct net_device *dev,
-                       int iface, struct can_frame *frame, int objno)
+static void c_can_setup_tx_object(struct net_device *dev, int iface,
+                                 struct can_frame *frame, int idx)
 {
-       int i;
-       u16 flags = 0;
-       unsigned int id;
        struct c_can_priv *priv = netdev_priv(dev);
-
-       if (!(frame->can_id & CAN_RTR_FLAG))
-               flags |= IF_ARB_TRANSMIT;
+       u16 ctrl = IF_MCONT_TX | frame->can_dlc;
+       bool rtr = frame->can_id & CAN_RTR_FLAG;
+       u32 arb = IF_ARB_MSGVAL;
+       int i;
 
        if (frame->can_id & CAN_EFF_FLAG) {
-               id = frame->can_id & CAN_EFF_MASK;
-               flags |= IF_ARB_MSGXTD;
-       } else
-               id = ((frame->can_id & CAN_SFF_MASK) << 18);
+               arb |= frame->can_id & CAN_EFF_MASK;
+               arb |= IF_ARB_MSGXTD;
+       } else {
+               arb |= (frame->can_id & CAN_SFF_MASK) << 18;
+       }
+
+       if (!rtr)
+               arb |= IF_ARB_TRANSMIT;
+
+       /*
+        * If we change the DIR bit, we need to invalidate the buffer
+        * first, i.e. clear the MSGVAL flag in the arbiter.
+        */
+       if (rtr != (bool)test_bit(idx, &priv->tx_dir)) {
+               u32 obj = idx + C_CAN_MSG_OBJ_TX_FIRST;
+
+               c_can_inval_msg_object(dev, iface, obj);
+               change_bit(idx, &priv->tx_dir);
+       }
 
-       flags |= IF_ARB_MSGVAL;
+       priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), arb);
+       priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), arb >> 16);
 
-       priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface),
-                               IFX_WRITE_LOW_16BIT(id));
-       priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), flags |
-                               IFX_WRITE_HIGH_16BIT(id));
+       priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl);
 
        for (i = 0; i < frame->can_dlc; i += 2) {
                priv->write_reg(priv, C_CAN_IFACE(DATA1_REG, iface) + i / 2,
                                frame->data[i] | (frame->data[i + 1] << 8));
        }
-
-       /* enable interrupt for this message object */
-       priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface),
-                       IF_MCONT_TXIE | IF_MCONT_TXRQST | IF_MCONT_EOB |
-                       frame->can_dlc);
-       c_can_object_put(dev, iface, objno, IF_COMM_ALL);
 }
 
 static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev,
-                                               int iface,
-                                               int ctrl_mask)
+                                                      int iface)
 {
        int i;
-       struct c_can_priv *priv = netdev_priv(dev);
 
-       for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++) {
-               priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface),
-                               ctrl_mask & ~IF_MCONT_NEWDAT);
-               c_can_object_put(dev, iface, i, IF_COMM_CONTROL);
-       }
+       for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++)
+               c_can_object_get(dev, iface, i, IF_COMM_CLR_NEWDAT);
 }
 
 static int c_can_handle_lost_msg_obj(struct net_device *dev,
@@ -377,6 +360,9 @@ static int c_can_handle_lost_msg_obj(struct net_device *dev,
        priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl);
        c_can_object_put(dev, iface, objno, IF_COMM_CONTROL);
 
+       stats->rx_errors++;
+       stats->rx_over_errors++;
+
        /* create an error msg */
        skb = alloc_can_err_skb(dev, &frame);
        if (unlikely(!skb))
@@ -384,22 +370,18 @@ static int c_can_handle_lost_msg_obj(struct net_device *dev,
 
        frame->can_id |= CAN_ERR_CRTL;
        frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
-       stats->rx_errors++;
-       stats->rx_over_errors++;
 
        netif_receive_skb(skb);
        return 1;
 }
 
-static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl)
+static int c_can_read_msg_object(struct net_device *dev, int iface, u32 ctrl)
 {
-       u16 flags, data;
-       int i;
-       unsigned int val;
-       struct c_can_priv *priv = netdev_priv(dev);
        struct net_device_stats *stats = &dev->stats;
-       struct sk_buff *skb;
+       struct c_can_priv *priv = netdev_priv(dev);
        struct can_frame *frame;
+       struct sk_buff *skb;
+       u32 arb, data;
 
        skb = alloc_can_skb(dev, &frame);
        if (!skb) {
@@ -409,115 +391,82 @@ static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl)
 
        frame->can_dlc = get_can_dlc(ctrl & 0x0F);
 
-       flags = priv->read_reg(priv, C_CAN_IFACE(ARB2_REG, iface));
-       val = priv->read_reg(priv, C_CAN_IFACE(ARB1_REG, iface)) |
-               (flags << 16);
+       arb = priv->read_reg(priv, C_CAN_IFACE(ARB1_REG, iface));
+       arb |= priv->read_reg(priv, C_CAN_IFACE(ARB2_REG, iface)) << 16;
 
-       if (flags & IF_ARB_MSGXTD)
-               frame->can_id = (val & CAN_EFF_MASK) | CAN_EFF_FLAG;
+       if (arb & IF_ARB_MSGXTD)
+               frame->can_id = (arb & CAN_EFF_MASK) | CAN_EFF_FLAG;
        else
-               frame->can_id = (val >> 18) & CAN_SFF_MASK;
+               frame->can_id = (arb >> 18) & CAN_SFF_MASK;
 
-       if (flags & IF_ARB_TRANSMIT)
+       if (arb & IF_ARB_TRANSMIT) {
                frame->can_id |= CAN_RTR_FLAG;
-       else {
-               for (i = 0; i < frame->can_dlc; i += 2) {
-                       data = priv->read_reg(priv,
-                               C_CAN_IFACE(DATA1_REG, iface) + i / 2);
+       } else {
+               int i, dreg = C_CAN_IFACE(DATA1_REG, iface);
+
+               for (i = 0; i < frame->can_dlc; i += 2, dreg ++) {
+                       data = priv->read_reg(priv, dreg);
                        frame->data[i] = data;
                        frame->data[i + 1] = data >> 8;
                }
        }
 
-       netif_receive_skb(skb);
-
        stats->rx_packets++;
        stats->rx_bytes += frame->can_dlc;
+
+       netif_receive_skb(skb);
        return 0;
 }
 
 static void c_can_setup_receive_object(struct net_device *dev, int iface,
-                                       int objno, unsigned int mask,
-                                       unsigned int id, unsigned int mcont)
+                                      u32 obj, u32 mask, u32 id, u32 mcont)
 {
        struct c_can_priv *priv = netdev_priv(dev);
 
-       priv->write_reg(priv, C_CAN_IFACE(MASK1_REG, iface),
-                       IFX_WRITE_LOW_16BIT(mask));
-
-       /* According to C_CAN documentation, the reserved bit
-        * in IFx_MASK2 register is fixed 1
-        */
-       priv->write_reg(priv, C_CAN_IFACE(MASK2_REG, iface),
-                       IFX_WRITE_HIGH_16BIT(mask) | BIT(13));
+       mask |= BIT(29);
+       priv->write_reg(priv, C_CAN_IFACE(MASK1_REG, iface), mask);
+       priv->write_reg(priv, C_CAN_IFACE(MASK2_REG, iface), mask >> 16);
 
-       priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface),
-                       IFX_WRITE_LOW_16BIT(id));
-       priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface),
-                       (IF_ARB_MSGVAL | IFX_WRITE_HIGH_16BIT(id)));
+       id |= IF_ARB_MSGVAL;
+       priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), id);
+       priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), id >> 16);
 
        priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), mcont);
-       c_can_object_put(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST);
-
-       netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno,
-                       c_can_read_reg32(priv, C_CAN_MSGVAL1_REG));
-}
-
-static void c_can_inval_msg_object(struct net_device *dev, int iface, int objno)
-{
-       struct c_can_priv *priv = netdev_priv(dev);
-
-       priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), 0);
-       priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), 0);
-       priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0);
-
-       c_can_object_put(dev, iface, objno, IF_COMM_ARB | IF_COMM_CONTROL);
-
-       netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno,
-                       c_can_read_reg32(priv, C_CAN_MSGVAL1_REG));
-}
-
-static inline int c_can_is_next_tx_obj_busy(struct c_can_priv *priv, int objno)
-{
-       int val = c_can_read_reg32(priv, C_CAN_TXRQST1_REG);
-
-       /*
-        * as transmission request register's bit n-1 corresponds to
-        * message object n, we need to handle the same properly.
-        */
-       if (val & (1 << (objno - 1)))
-               return 1;
-
-       return 0;
+       c_can_object_put(dev, iface, obj, IF_COMM_RCV_SETUP);
 }
 
 static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
-                                       struct net_device *dev)
+                                   struct net_device *dev)
 {
-       u32 msg_obj_no;
-       struct c_can_priv *priv = netdev_priv(dev);
        struct can_frame *frame = (struct can_frame *)skb->data;
+       struct c_can_priv *priv = netdev_priv(dev);
+       u32 idx, obj;
 
        if (can_dropped_invalid_skb(dev, skb))
                return NETDEV_TX_OK;
-
-       spin_lock_bh(&priv->xmit_lock);
-       msg_obj_no = get_tx_next_msg_obj(priv);
-
-       /* prepare message object for transmission */
-       c_can_write_msg_object(dev, IF_TX, frame, msg_obj_no);
-       priv->dlc[msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST] = frame->can_dlc;
-       can_put_echo_skb(skb, dev, msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
-
        /*
-        * we have to stop the queue in case of a wrap around or
-        * if the next TX message object is still in use
+        * This is not a FIFO. C/D_CAN sends out the buffers
+        * prioritized. The lowest buffer number wins.
         */
-       priv->tx_next++;
-       if (c_can_is_next_tx_obj_busy(priv, get_tx_next_msg_obj(priv)) ||
-                       (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) == 0)
+       idx = fls(atomic_read(&priv->tx_active));
+       obj = idx + C_CAN_MSG_OBJ_TX_FIRST;
+
+       /* If this is the last buffer, stop the xmit queue */
+       if (idx == C_CAN_MSG_OBJ_TX_NUM - 1)
                netif_stop_queue(dev);
-       spin_unlock_bh(&priv->xmit_lock);
+       /*
+        * Store the message in the interface so we can call
+        * can_put_echo_skb(). We must do this before we enable
+        * transmit as we might race against do_tx().
+        */
+       c_can_setup_tx_object(dev, IF_TX, frame, idx);
+       priv->dlc[idx] = frame->can_dlc;
+       can_put_echo_skb(skb, dev, idx);
+
+       /* Update the active bits */
+       atomic_add((1 << idx), &priv->tx_active);
+       /* Start transmission */
+       c_can_object_put(dev, IF_TX, obj, IF_COMM_TX);
 
        return NETDEV_TX_OK;
 }
@@ -594,11 +543,10 @@ static void c_can_configure_msg_objects(struct net_device *dev)
 
        /* setup receive message objects */
        for (i = C_CAN_MSG_OBJ_RX_FIRST; i < C_CAN_MSG_OBJ_RX_LAST; i++)
-               c_can_setup_receive_object(dev, IF_RX, i, 0, 0,
-                       (IF_MCONT_RXIE | IF_MCONT_UMASK) & ~IF_MCONT_EOB);
+               c_can_setup_receive_object(dev, IF_RX, i, 0, 0, IF_MCONT_RCV);
 
        c_can_setup_receive_object(dev, IF_RX, C_CAN_MSG_OBJ_RX_LAST, 0, 0,
-                       IF_MCONT_EOB | IF_MCONT_RXIE | IF_MCONT_UMASK);
+                                  IF_MCONT_RCV_EOB);
 }
 
 /*
@@ -612,30 +560,22 @@ static int c_can_chip_config(struct net_device *dev)
        struct c_can_priv *priv = netdev_priv(dev);
 
        /* enable automatic retransmission */
-       priv->write_reg(priv, C_CAN_CTRL_REG,
-                       CONTROL_ENABLE_AR);
+       priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR);
 
        if ((priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) &&
            (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)) {
                /* loopback + silent mode : useful for hot self-test */
-               priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE |
-                               CONTROL_SIE | CONTROL_IE | CONTROL_TEST);
-               priv->write_reg(priv, C_CAN_TEST_REG,
-                               TEST_LBACK | TEST_SILENT);
+               priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);
+               priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK | TEST_SILENT);
        } else if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
                /* loopback mode : useful for self-test function */
-               priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE |
-                               CONTROL_SIE | CONTROL_IE | CONTROL_TEST);
+               priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);
                priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK);
        } else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
                /* silent mode : bus-monitoring mode */
-               priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE |
-                               CONTROL_SIE | CONTROL_IE | CONTROL_TEST);
+               priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);
                priv->write_reg(priv, C_CAN_TEST_REG, TEST_SILENT);
-       } else
-               /* normal mode*/
-               priv->write_reg(priv, C_CAN_CTRL_REG,
-                               CONTROL_EIE | CONTROL_SIE | CONTROL_IE);
+       }
 
        /* configure message objects */
        c_can_configure_msg_objects(dev);
@@ -643,6 +583,11 @@ static int c_can_chip_config(struct net_device *dev)
        /* set a `lec` value so that we can check for updates later */
        priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED);
 
+       /* Clear all internal status */
+       atomic_set(&priv->tx_active, 0);
+       priv->rxmasked = 0;
+       priv->tx_dir = 0;
+
        /* set bittiming params */
        return c_can_set_bittiming(dev);
 }
@@ -657,13 +602,11 @@ static int c_can_start(struct net_device *dev)
        if (err)
                return err;
 
-       priv->can.state = CAN_STATE_ERROR_ACTIVE;
-
-       /* reset tx helper pointers */
-       priv->tx_next = priv->tx_echo = 0;
+       /* Setup the command for new messages */
+       priv->comm_rcv_high = priv->type != BOSCH_D_CAN ?
+               IF_COMM_RCV_LOW : IF_COMM_RCV_HIGH;
 
-       /* enable status change, error and module interrupts */
-       c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
+       priv->can.state = CAN_STATE_ERROR_ACTIVE;
 
        return 0;
 }
@@ -672,15 +615,13 @@ static void c_can_stop(struct net_device *dev)
 {
        struct c_can_priv *priv = netdev_priv(dev);
 
-       /* disable all interrupts */
-       c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
-
-       /* set the state as STOPPED */
+       c_can_irq_control(priv, false);
        priv->can.state = CAN_STATE_STOPPED;
 }
 
 static int c_can_set_mode(struct net_device *dev, enum can_mode mode)
 {
+       struct c_can_priv *priv = netdev_priv(dev);
        int err;
 
        switch (mode) {
@@ -689,6 +630,7 @@ static int c_can_set_mode(struct net_device *dev, enum can_mode mode)
                if (err)
                        return err;
                netif_wake_queue(dev);
+               c_can_irq_control(priv, true);
                break;
        default:
                return -EOPNOTSUPP;
@@ -724,42 +666,29 @@ static int c_can_get_berr_counter(const struct net_device *dev,
        return err;
 }
 
-/*
- * priv->tx_echo holds the number of the oldest can_frame put for
- * transmission into the hardware, but not yet ACKed by the CAN tx
- * complete IRQ.
- *
- * We iterate from priv->tx_echo to priv->tx_next and check if the
- * packet has been transmitted, echo it back to the CAN framework.
- * If we discover a not yet transmitted packet, stop looking for more.
- */
 static void c_can_do_tx(struct net_device *dev)
 {
        struct c_can_priv *priv = netdev_priv(dev);
        struct net_device_stats *stats = &dev->stats;
-       u32 val, obj, pkts = 0, bytes = 0;
-
-       spin_lock_bh(&priv->xmit_lock);
-
-       for (; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) {
-               obj = get_tx_echo_msg_obj(priv->tx_echo);
-               val = c_can_read_reg32(priv, C_CAN_TXRQST1_REG);
+       u32 idx, obj, pkts = 0, bytes = 0, pend, clr;
 
-               if (val & (1 << (obj - 1)))
-                       break;
+       clr = pend = priv->read_reg(priv, C_CAN_INTPND2_REG);
 
-               can_get_echo_skb(dev, obj - C_CAN_MSG_OBJ_TX_FIRST);
-               bytes += priv->dlc[obj - C_CAN_MSG_OBJ_TX_FIRST];
+       while ((idx = ffs(pend))) {
+               idx--;
+               pend &= ~(1 << idx);
+               obj = idx + C_CAN_MSG_OBJ_TX_FIRST;
+               c_can_inval_tx_object(dev, IF_RX, obj);
+               can_get_echo_skb(dev, idx);
+               bytes += priv->dlc[idx];
                pkts++;
-               c_can_inval_msg_object(dev, IF_TX, obj);
        }
 
-       /* restart queue if wrap-up or if queue stalled on last pkt */
-       if (((priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) != 0) ||
-                       ((priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) == 0))
-               netif_wake_queue(dev);
+       /* Clear the bits in the tx_active mask */
+       atomic_sub(clr, &priv->tx_active);
 
-       spin_unlock_bh(&priv->xmit_lock);
+       if (clr & (1 << (C_CAN_MSG_OBJ_TX_NUM - 1)))
+               netif_wake_queue(dev);
 
        if (pkts) {
                stats->tx_bytes += bytes;
@@ -800,18 +729,28 @@ static u32 c_can_adjust_pending(u32 pend)
        return pend & ~((1 << lasts) - 1);
 }
 
+static inline void c_can_rx_object_get(struct net_device *dev,
+                                      struct c_can_priv *priv, u32 obj)
+{
+               c_can_object_get(dev, IF_RX, obj, priv->comm_rcv_high);
+}
+
+static inline void c_can_rx_finalize(struct net_device *dev,
+                                    struct c_can_priv *priv, u32 obj)
+{
+       if (priv->type != BOSCH_D_CAN)
+               c_can_object_get(dev, IF_RX, obj, IF_COMM_CLR_NEWDAT);
+}
+
 static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
                              u32 pend, int quota)
 {
-       u32 pkts = 0, ctrl, obj, mcmd;
+       u32 pkts = 0, ctrl, obj;
 
        while ((obj = ffs(pend)) && quota > 0) {
                pend &= ~BIT(obj - 1);
 
-               mcmd = obj < C_CAN_MSG_RX_LOW_LAST ?
-                       IF_COMM_RCV_LOW : IF_COMM_RCV_HIGH;
-
-               c_can_object_get(dev, IF_RX, obj, mcmd);
+               c_can_rx_object_get(dev, priv, obj);
                ctrl = priv->read_reg(priv, C_CAN_IFACE(MSGCTRL_REG, IF_RX));
 
                if (ctrl & IF_MCONT_MSGLST) {
@@ -833,9 +772,7 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
                /* read the data from the message object */
                c_can_read_msg_object(dev, IF_RX, ctrl);
 
-               if (obj == C_CAN_MSG_RX_LOW_LAST)
-                       /* activate all lower message objects */
-                       c_can_activate_all_lower_rx_msg_obj(dev, IF_RX, ctrl);
+               c_can_rx_finalize(dev, priv, obj);
 
                pkts++;
                quota--;
@@ -844,6 +781,13 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
        return pkts;
 }
 
+static inline u32 c_can_get_pending(struct c_can_priv *priv)
+{
+       u32 pend = priv->read_reg(priv, C_CAN_NEWDAT1_REG);
+
+       return pend;
+}
+
 /*
  * theory of operation:
  *
@@ -853,18 +797,9 @@ static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
  * has arrived. To work-around this issue, we keep two groups of message
  * objects whose partitioning is defined by C_CAN_MSG_OBJ_RX_SPLIT.
  *
- * To ensure in-order frame reception we use the following
- * approach while re-activating a message object to receive further
- * frames:
- * - if the current message object number is lower than
- *   C_CAN_MSG_RX_LOW_LAST, do not clear the NEWDAT bit while clearing
- *   the INTPND bit.
- * - if the current message object number is equal to
- *   C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of all lower
- *   receive message objects.
- * - if the current message object number is greater than
- *   C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of
- *   only this message object.
+ * We clear the newdat bit right away.
+ *
+ * This can result in packet reordering when the readout is slow.
  */
 static int c_can_do_rx_poll(struct net_device *dev, int quota)
 {
@@ -880,7 +815,7 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota)
 
        while (quota > 0) {
                if (!pend) {
-                       pend = priv->read_reg(priv, C_CAN_INTPND1_REG);
+                       pend = c_can_get_pending(priv);
                        if (!pend)
                                break;
                        /*
@@ -905,12 +840,6 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota)
        return pkts;
 }
 
-static inline int c_can_has_and_handle_berr(struct c_can_priv *priv)
-{
-       return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) &&
-               (priv->current_status & LEC_UNUSED);
-}
-
 static int c_can_handle_state_change(struct net_device *dev,
                                enum c_can_bus_error_types error_type)
 {
@@ -922,6 +851,26 @@ static int c_can_handle_state_change(struct net_device *dev,
        struct sk_buff *skb;
        struct can_berr_counter bec;
 
+       switch (error_type) {
+       case C_CAN_ERROR_WARNING:
+               /* error warning state */
+               priv->can.can_stats.error_warning++;
+               priv->can.state = CAN_STATE_ERROR_WARNING;
+               break;
+       case C_CAN_ERROR_PASSIVE:
+               /* error passive state */
+               priv->can.can_stats.error_passive++;
+               priv->can.state = CAN_STATE_ERROR_PASSIVE;
+               break;
+       case C_CAN_BUS_OFF:
+               /* bus-off state */
+               priv->can.state = CAN_STATE_BUS_OFF;
+               can_bus_off(dev);
+               break;
+       default:
+               break;
+       }
+
        /* propagate the error condition to the CAN stack */
        skb = alloc_can_err_skb(dev, &cf);
        if (unlikely(!skb))
@@ -935,8 +884,6 @@ static int c_can_handle_state_change(struct net_device *dev,
        switch (error_type) {
        case C_CAN_ERROR_WARNING:
                /* error warning state */
-               priv->can.can_stats.error_warning++;
-               priv->can.state = CAN_STATE_ERROR_WARNING;
                cf->can_id |= CAN_ERR_CRTL;
                cf->data[1] = (bec.txerr > bec.rxerr) ?
                        CAN_ERR_CRTL_TX_WARNING :
@@ -947,8 +894,6 @@ static int c_can_handle_state_change(struct net_device *dev,
                break;
        case C_CAN_ERROR_PASSIVE:
                /* error passive state */
-               priv->can.can_stats.error_passive++;
-               priv->can.state = CAN_STATE_ERROR_PASSIVE;
                cf->can_id |= CAN_ERR_CRTL;
                if (rx_err_passive)
                        cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
@@ -960,22 +905,16 @@ static int c_can_handle_state_change(struct net_device *dev,
                break;
        case C_CAN_BUS_OFF:
                /* bus-off state */
-               priv->can.state = CAN_STATE_BUS_OFF;
                cf->can_id |= CAN_ERR_BUSOFF;
-               /*
-                * disable all interrupts in bus-off mode to ensure that
-                * the CPU is not hogged down
-                */
-               c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
                can_bus_off(dev);
                break;
        default:
                break;
        }
 
-       netif_receive_skb(skb);
        stats->rx_packets++;
        stats->rx_bytes += cf->can_dlc;
+       netif_receive_skb(skb);
 
        return 1;
 }
@@ -996,6 +935,13 @@ static int c_can_handle_bus_err(struct net_device *dev,
        if (lec_type == LEC_UNUSED || lec_type == LEC_NO_ERROR)
                return 0;
 
+       if (!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING))
+               return 0;
+
+       /* common for all type of bus errors */
+       priv->can.can_stats.bus_error++;
+       stats->rx_errors++;
+
        /* propagate the error condition to the CAN stack */
        skb = alloc_can_err_skb(dev, &cf);
        if (unlikely(!skb))
@@ -1005,10 +951,6 @@ static int c_can_handle_bus_err(struct net_device *dev,
         * check for 'last error code' which tells us the
         * type of the last error to occur on the CAN bus
         */
-
-       /* common for all type of bus errors */
-       priv->can.can_stats.bus_error++;
-       stats->rx_errors++;
        cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
        cf->data[2] |= CAN_ERR_PROT_UNSPEC;
 
@@ -1043,95 +985,64 @@ static int c_can_handle_bus_err(struct net_device *dev,
                break;
        }
 
-       /* set a `lec` value so that we can check for updates later */
-       priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED);
-
-       netif_receive_skb(skb);
        stats->rx_packets++;
        stats->rx_bytes += cf->can_dlc;
-
+       netif_receive_skb(skb);
        return 1;
 }
 
 static int c_can_poll(struct napi_struct *napi, int quota)
 {
-       u16 irqstatus;
-       int lec_type = 0;
-       int work_done = 0;
        struct net_device *dev = napi->dev;
        struct c_can_priv *priv = netdev_priv(dev);
+       u16 curr, last = priv->last_status;
+       int work_done = 0;
 
-       irqstatus = priv->irqstatus;
-       if (!irqstatus)
-               goto end;
+       priv->last_status = curr = priv->read_reg(priv, C_CAN_STS_REG);
+       /* Ack status on C_CAN. D_CAN is self clearing */
+       if (priv->type != BOSCH_D_CAN)
+               priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED);
 
-       /* status events have the highest priority */
-       if (irqstatus == STATUS_INTERRUPT) {
-               priv->current_status = priv->read_reg(priv,
-                                       C_CAN_STS_REG);
-
-               /* handle Tx/Rx events */
-               if (priv->current_status & STATUS_TXOK)
-                       priv->write_reg(priv, C_CAN_STS_REG,
-                                       priv->current_status & ~STATUS_TXOK);
-
-               if (priv->current_status & STATUS_RXOK)
-                       priv->write_reg(priv, C_CAN_STS_REG,
-                                       priv->current_status & ~STATUS_RXOK);
-
-               /* handle state changes */
-               if ((priv->current_status & STATUS_EWARN) &&
-                               (!(priv->last_status & STATUS_EWARN))) {
-                       netdev_dbg(dev, "entered error warning state\n");
-                       work_done += c_can_handle_state_change(dev,
-                                               C_CAN_ERROR_WARNING);
-               }
-               if ((priv->current_status & STATUS_EPASS) &&
-                               (!(priv->last_status & STATUS_EPASS))) {
-                       netdev_dbg(dev, "entered error passive state\n");
-                       work_done += c_can_handle_state_change(dev,
-                                               C_CAN_ERROR_PASSIVE);
-               }
-               if ((priv->current_status & STATUS_BOFF) &&
-                               (!(priv->last_status & STATUS_BOFF))) {
-                       netdev_dbg(dev, "entered bus off state\n");
-                       work_done += c_can_handle_state_change(dev,
-                                               C_CAN_BUS_OFF);
-               }
+       /* handle state changes */
+       if ((curr & STATUS_EWARN) && (!(last & STATUS_EWARN))) {
+               netdev_dbg(dev, "entered error warning state\n");
+               work_done += c_can_handle_state_change(dev, C_CAN_ERROR_WARNING);
+       }
 
-               /* handle bus recovery events */
-               if ((!(priv->current_status & STATUS_BOFF)) &&
-                               (priv->last_status & STATUS_BOFF)) {
-                       netdev_dbg(dev, "left bus off state\n");
-                       priv->can.state = CAN_STATE_ERROR_ACTIVE;
-               }
-               if ((!(priv->current_status & STATUS_EPASS)) &&
-                               (priv->last_status & STATUS_EPASS)) {
-                       netdev_dbg(dev, "left error passive state\n");
-                       priv->can.state = CAN_STATE_ERROR_ACTIVE;
-               }
+       if ((curr & STATUS_EPASS) && (!(last & STATUS_EPASS))) {
+               netdev_dbg(dev, "entered error passive state\n");
+               work_done += c_can_handle_state_change(dev, C_CAN_ERROR_PASSIVE);
+       }
 
-               priv->last_status = priv->current_status;
-
-               /* handle lec errors on the bus */
-               lec_type = c_can_has_and_handle_berr(priv);
-               if (lec_type)
-                       work_done += c_can_handle_bus_err(dev, lec_type);
-       } else if ((irqstatus >= C_CAN_MSG_OBJ_RX_FIRST) &&
-                       (irqstatus <= C_CAN_MSG_OBJ_RX_LAST)) {
-               /* handle events corresponding to receive message objects */
-               work_done += c_can_do_rx_poll(dev, (quota - work_done));
-       } else if ((irqstatus >= C_CAN_MSG_OBJ_TX_FIRST) &&
-                       (irqstatus <= C_CAN_MSG_OBJ_TX_LAST)) {
-               /* handle events corresponding to transmit message objects */
-               c_can_do_tx(dev);
+       if ((curr & STATUS_BOFF) && (!(last & STATUS_BOFF))) {
+               netdev_dbg(dev, "entered bus off state\n");
+               work_done += c_can_handle_state_change(dev, C_CAN_BUS_OFF);
+               goto end;
        }
 
+       /* handle bus recovery events */
+       if ((!(curr & STATUS_BOFF)) && (last & STATUS_BOFF)) {
+               netdev_dbg(dev, "left bus off state\n");
+               priv->can.state = CAN_STATE_ERROR_ACTIVE;
+       }
+       if ((!(curr & STATUS_EPASS)) && (last & STATUS_EPASS)) {
+               netdev_dbg(dev, "left error passive state\n");
+               priv->can.state = CAN_STATE_ERROR_ACTIVE;
+       }
+
+       /* handle lec errors on the bus */
+       work_done += c_can_handle_bus_err(dev, curr & LEC_MASK);
+
+       /* Handle Tx/Rx events. We do this unconditionally */
+       work_done += c_can_do_rx_poll(dev, (quota - work_done));
+       c_can_do_tx(dev);
+
 end:
        if (work_done < quota) {
                napi_complete(napi);
-               /* enable all IRQs */
-               c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
+               /* enable all IRQs if we are not in bus off state */
+               if (priv->can.state != CAN_STATE_BUS_OFF)
+                       c_can_irq_control(priv, true);
        }
 
        return work_done;
@@ -1142,12 +1053,11 @@ static irqreturn_t c_can_isr(int irq, void *dev_id)
        struct net_device *dev = (struct net_device *)dev_id;
        struct c_can_priv *priv = netdev_priv(dev);
 
-       priv->irqstatus = priv->read_reg(priv, C_CAN_INT_REG);
-       if (!priv->irqstatus)
+       if (!priv->read_reg(priv, C_CAN_INT_REG))
                return IRQ_NONE;
 
        /* disable all interrupts and schedule the NAPI */
-       c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
+       c_can_irq_control(priv, false);
        napi_schedule(&priv->napi);
 
        return IRQ_HANDLED;
@@ -1184,6 +1094,8 @@ static int c_can_open(struct net_device *dev)
        can_led_event(dev, CAN_LED_EVENT_OPEN);
 
        napi_enable(&priv->napi);
+       /* enable status change, error and module interrupts */
+       c_can_irq_control(priv, true);
        netif_start_queue(dev);
 
        return 0;
@@ -1226,7 +1138,6 @@ struct net_device *alloc_c_can_dev(void)
                return NULL;
 
        priv = netdev_priv(dev);
-       spin_lock_init(&priv->xmit_lock);
        netif_napi_add(dev, &priv->napi, c_can_poll, C_CAN_NAPI_WEIGHT);
 
        priv->dev = dev;
@@ -1281,6 +1192,7 @@ int c_can_power_up(struct net_device *dev)
        u32 val;
        unsigned long time_out;
        struct c_can_priv *priv = netdev_priv(dev);
+       int ret;
 
        if (!(dev->flags & IFF_UP))
                return 0;
@@ -1307,7 +1219,11 @@ int c_can_power_up(struct net_device *dev)
        if (time_after(jiffies, time_out))
                return -ETIMEDOUT;
 
-       return c_can_start(dev);
+       ret = c_can_start(dev);
+       if (!ret)
+               c_can_irq_control(priv, true);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(c_can_power_up);
 #endif
index faa8404162b397e4bd589c0b7b665c2f6ab1e4e4..c56f1b1c11cacde9e41c5cd663fd69ce802f2025 100644 (file)
 #ifndef C_CAN_H
 #define C_CAN_H
 
-/*
- * IFx register masks:
- * allow easy operation on 16-bit registers when the
- * argument is 32-bit instead
- */
-#define IFX_WRITE_LOW_16BIT(x) ((x) & 0xFFFF)
-#define IFX_WRITE_HIGH_16BIT(x)        (((x) & 0xFFFF0000) >> 16)
-
 /* message object split */
 #define C_CAN_NO_OF_OBJECTS    32
 #define C_CAN_MSG_OBJ_RX_NUM   16
@@ -45,8 +37,6 @@
 
 #define C_CAN_MSG_OBJ_RX_SPLIT 9
 #define C_CAN_MSG_RX_LOW_LAST  (C_CAN_MSG_OBJ_RX_SPLIT - 1)
-
-#define C_CAN_NEXT_MSG_OBJ_MASK        (C_CAN_MSG_OBJ_TX_NUM - 1)
 #define RECEIVE_OBJECT_BITS    0x0000ffff
 
 enum reg {
@@ -183,23 +173,20 @@ struct c_can_priv {
        struct napi_struct napi;
        struct net_device *dev;
        struct device *device;
-       spinlock_t xmit_lock;
-       int tx_object;
-       int current_status;
+       atomic_t tx_active;
+       unsigned long tx_dir;
        int last_status;
        u16 (*read_reg) (struct c_can_priv *priv, enum reg index);
        void (*write_reg) (struct c_can_priv *priv, enum reg index, u16 val);
        void __iomem *base;
        const u16 *regs;
-       unsigned long irq_flags; /* for request_irq() */
-       unsigned int tx_next;
-       unsigned int tx_echo;
        void *priv;             /* for board-specific data */
-       u16 irqstatus;
        enum c_can_dev_id type;
        u32 __iomem *raminit_ctrlreg;
-       unsigned int instance;
+       int instance;
        void (*raminit) (const struct c_can_priv *priv, bool enable);
+       u32 comm_rcv_high;
+       u32 rxmasked;
        u32 dlc[C_CAN_MSG_OBJ_TX_NUM];
 };
 
index bce0be54c2f59587a2498d2f37821f2634b886d9..fe5f6303b58400fb69913229c20da6a2f2a5d303 100644 (file)
@@ -84,8 +84,11 @@ static int c_can_pci_probe(struct pci_dev *pdev,
                goto out_disable_device;
        }
 
-       pci_set_master(pdev);
-       pci_enable_msi(pdev);
+       ret = pci_enable_msi(pdev);
+       if (!ret) {
+               dev_info(&pdev->dev, "MSI enabled\n");
+               pci_set_master(pdev);
+       }
 
        addr = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
        if (!addr) {
@@ -132,6 +135,8 @@ static int c_can_pci_probe(struct pci_dev *pdev,
                goto out_free_c_can;
        }
 
+       priv->type = c_can_pci_data->type;
+
        /* Configure access to registers */
        switch (c_can_pci_data->reg_align) {
        case C_CAN_REG_ALIGN_32:
index 806d92753427b619fe7241ac290a18aa7769240b..1df0b322d1e461ee69c4e74a499f425cda23d7bf 100644 (file)
@@ -222,7 +222,7 @@ static int c_can_plat_probe(struct platform_device *pdev)
 
                res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
                priv->raminit_ctrlreg = devm_ioremap_resource(&pdev->dev, res);
-               if (IS_ERR(priv->raminit_ctrlreg) || (int)priv->instance < 0)
+               if (IS_ERR(priv->raminit_ctrlreg) || priv->instance < 0)
                        dev_info(&pdev->dev, "control memory is not used for raminit\n");
                else
                        priv->raminit = c_can_hw_raminit;
index c7a260478749ad163ec133df88e7a0086b220a73..e318e87e2bfc00ba9e32aa08858de5f5c1629dcf 100644 (file)
@@ -256,7 +256,7 @@ static int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt,
 
        /* Check if the CAN device has bit-timing parameters */
        if (!btc)
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        /*
         * Depending on the given can_bittiming parameter structure the CAN
index c540e3d12e3d826260dbb590e8045c92fa4efb2b..564933ae218c78848dfba1e166f219e9de994e79 100644 (file)
@@ -551,7 +551,7 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct sja1000_priv *priv;
        struct peak_pci_chan *chan;
-       struct net_device *dev;
+       struct net_device *dev, *prev_dev;
        void __iomem *cfg_base, *reg_base;
        u16 sub_sys_id, icr;
        int i, err, channels;
@@ -688,11 +688,13 @@ failure_remove_channels:
        writew(0x0, cfg_base + PITA_ICR + 2);
 
        chan = NULL;
-       for (dev = pci_get_drvdata(pdev); dev; dev = chan->prev_dev) {
-               unregister_sja1000dev(dev);
-               free_sja1000dev(dev);
+       for (dev = pci_get_drvdata(pdev); dev; dev = prev_dev) {
                priv = netdev_priv(dev);
                chan = priv->priv;
+               prev_dev = chan->prev_dev;
+
+               unregister_sja1000dev(dev);
+               free_sja1000dev(dev);
        }
 
        /* free any PCIeC resources too */
@@ -726,10 +728,12 @@ static void peak_pci_remove(struct pci_dev *pdev)
 
        /* Loop over all registered devices */
        while (1) {
+               struct net_device *prev_dev = chan->prev_dev;
+
                dev_info(&pdev->dev, "removing device %s\n", dev->name);
                unregister_sja1000dev(dev);
                free_sja1000dev(dev);
-               dev = chan->prev_dev;
+               dev = prev_dev;
 
                if (!dev) {
                        /* do that only for first channel */
index df136a2516c401a5d96aba3d7c0da2e9f511d1a8..014695d7e6a342c49e9c86ed66f59ba5cddc0335 100644 (file)
@@ -46,6 +46,7 @@ static int clk[MAXDEV];
 static unsigned char cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
 static unsigned char ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
 static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
+static spinlock_t indirect_lock[MAXDEV];  /* lock for indirect access mode */
 
 module_param_array(port, ulong, NULL, S_IRUGO);
 MODULE_PARM_DESC(port, "I/O port number");
@@ -101,19 +102,26 @@ static void sja1000_isa_port_write_reg(const struct sja1000_priv *priv,
 static u8 sja1000_isa_port_read_reg_indirect(const struct sja1000_priv *priv,
                                             int reg)
 {
-       unsigned long base = (unsigned long)priv->reg_base;
+       unsigned long flags, base = (unsigned long)priv->reg_base;
+       u8 readval;
 
+       spin_lock_irqsave(&indirect_lock[priv->dev->dev_id], flags);
        outb(reg, base);
-       return inb(base + 1);
+       readval = inb(base + 1);
+       spin_unlock_irqrestore(&indirect_lock[priv->dev->dev_id], flags);
+
+       return readval;
 }
 
 static void sja1000_isa_port_write_reg_indirect(const struct sja1000_priv *priv,
                                                int reg, u8 val)
 {
-       unsigned long base = (unsigned long)priv->reg_base;
+       unsigned long flags, base = (unsigned long)priv->reg_base;
 
+       spin_lock_irqsave(&indirect_lock[priv->dev->dev_id], flags);
        outb(reg, base);
        outb(val, base + 1);
+       spin_unlock_irqrestore(&indirect_lock[priv->dev->dev_id], flags);
 }
 
 static int sja1000_isa_probe(struct platform_device *pdev)
@@ -169,6 +177,7 @@ static int sja1000_isa_probe(struct platform_device *pdev)
                if (iosize == SJA1000_IOSIZE_INDIRECT) {
                        priv->read_reg = sja1000_isa_port_read_reg_indirect;
                        priv->write_reg = sja1000_isa_port_write_reg_indirect;
+                       spin_lock_init(&indirect_lock[idx]);
                } else {
                        priv->read_reg = sja1000_isa_port_read_reg;
                        priv->write_reg = sja1000_isa_port_write_reg;
@@ -198,6 +207,7 @@ static int sja1000_isa_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
+       dev->dev_id = idx;
 
        err = register_sja1000dev(dev);
        if (err) {
index f5b16e0e3a125f4e38a93408e92b8218808339af..dcf9196f63164b0db099e17a8d1208d9ac158ac4 100644 (file)
@@ -322,13 +322,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);
+       spin_lock_bh(&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);
+               spin_unlock_bh(&sl->lock);
                netif_wake_queue(sl->dev);
                return;
        }
@@ -336,7 +336,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);
+       spin_unlock_bh(&sl->lock);
 }
 
 /* Send a can_frame to a TTY queue. */
index 39b26fe28d1051ff916faceb747da7a64dac711f..d7401017a3f10940f3a662bebc555d835be3ce4b 100644 (file)
@@ -35,6 +35,18 @@ source "drivers/net/ethernet/calxeda/Kconfig"
 source "drivers/net/ethernet/chelsio/Kconfig"
 source "drivers/net/ethernet/cirrus/Kconfig"
 source "drivers/net/ethernet/cisco/Kconfig"
+
+config CX_ECAT
+       tristate "Beckhoff CX5020 EtherCAT master support"
+       depends on PCI
+       ---help---
+         Driver for EtherCAT master module located on CCAT FPGA
+         that can be found on Beckhoff CX5020, and possibly other of CX
+         Beckhoff CX series industrial PCs.
+
+         To compile this driver as a module, choose M here. The module
+         will be called ec_bhf.
+
 source "drivers/net/ethernet/davicom/Kconfig"
 
 config DNET
index 545d0b3b9cb422b2fefa7122b074cd869a9085c2..35190e36c4568e6803279f878a6aa866685ca1be 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_NET_CALXEDA_XGMAC) += calxeda/
 obj-$(CONFIG_NET_VENDOR_CHELSIO) += chelsio/
 obj-$(CONFIG_NET_VENDOR_CIRRUS) += cirrus/
 obj-$(CONFIG_NET_VENDOR_CISCO) += cisco/
+obj-$(CONFIG_CX_ECAT) += ec_bhf.o
 obj-$(CONFIG_DM9000) += davicom/
 obj-$(CONFIG_DNET) += dnet.o
 obj-$(CONFIG_NET_VENDOR_DEC) += dec/
index 80c1ab74a4b8f36483ebe710aa56ffb3879d52bc..fdddba51473efce74edbf9c0befae1ebdfbe1824 100644 (file)
@@ -1,5 +1,6 @@
 config ALTERA_TSE
        tristate "Altera Triple-Speed Ethernet MAC support"
+       depends on HAS_DMA
        select PHYLIB
        ---help---
          This driver supports the Altera Triple-Speed (TSE) Ethernet MAC.
index d4a187e453698bbe96589921f97d5ea38bc3d5fb..3eff2fd3997e36ef128983fcaf080f595a693715 100644 (file)
@@ -5,3 +5,4 @@
 obj-$(CONFIG_ALTERA_TSE) += altera_tse.o
 altera_tse-objs := altera_tse_main.o altera_tse_ethtool.o \
 altera_msgdma.o altera_sgdma.o altera_utils.o
+ccflags-y += -D__CHECK_ENDIAN__
index 3df18669ea306580994cb877044a000aa4b7e6f9..0fb986ba32905a5dac78c926333c9765ec4678de 100644 (file)
@@ -18,6 +18,7 @@
 #include "altera_utils.h"
 #include "altera_tse.h"
 #include "altera_msgdmahw.h"
+#include "altera_msgdma.h"
 
 /* No initialization work to do for MSGDMA */
 int msgdma_initialize(struct altera_tse_private *priv)
@@ -29,21 +30,23 @@ void msgdma_uninitialize(struct altera_tse_private *priv)
 {
 }
 
+void msgdma_start_rxdma(struct altera_tse_private *priv)
+{
+}
+
 void msgdma_reset(struct altera_tse_private *priv)
 {
        int counter;
-       struct msgdma_csr *txcsr =
-               (struct msgdma_csr *)priv->tx_dma_csr;
-       struct msgdma_csr *rxcsr =
-               (struct msgdma_csr *)priv->rx_dma_csr;
 
        /* Reset Rx mSGDMA */
-       iowrite32(MSGDMA_CSR_STAT_MASK, &rxcsr->status);
-       iowrite32(MSGDMA_CSR_CTL_RESET, &rxcsr->control);
+       csrwr32(MSGDMA_CSR_STAT_MASK, priv->rx_dma_csr,
+               msgdma_csroffs(status));
+       csrwr32(MSGDMA_CSR_CTL_RESET, priv->rx_dma_csr,
+               msgdma_csroffs(control));
 
        counter = 0;
        while (counter++ < ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) {
-               if (tse_bit_is_clear(&rxcsr->status,
+               if (tse_bit_is_clear(priv->rx_dma_csr, msgdma_csroffs(status),
                                     MSGDMA_CSR_STAT_RESETTING))
                        break;
                udelay(1);
@@ -54,15 +57,18 @@ void msgdma_reset(struct altera_tse_private *priv)
                           "TSE Rx mSGDMA resetting bit never cleared!\n");
 
        /* clear all status bits */
-       iowrite32(MSGDMA_CSR_STAT_MASK, &rxcsr->status);
+       csrwr32(MSGDMA_CSR_STAT_MASK, priv->rx_dma_csr, msgdma_csroffs(status));
 
        /* Reset Tx mSGDMA */
-       iowrite32(MSGDMA_CSR_STAT_MASK, &txcsr->status);
-       iowrite32(MSGDMA_CSR_CTL_RESET, &txcsr->control);
+       csrwr32(MSGDMA_CSR_STAT_MASK, priv->tx_dma_csr,
+               msgdma_csroffs(status));
+
+       csrwr32(MSGDMA_CSR_CTL_RESET, priv->tx_dma_csr,
+               msgdma_csroffs(control));
 
        counter = 0;
        while (counter++ < ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) {
-               if (tse_bit_is_clear(&txcsr->status,
+               if (tse_bit_is_clear(priv->tx_dma_csr, msgdma_csroffs(status),
                                     MSGDMA_CSR_STAT_RESETTING))
                        break;
                udelay(1);
@@ -73,58 +79,58 @@ void msgdma_reset(struct altera_tse_private *priv)
                           "TSE Tx mSGDMA resetting bit never cleared!\n");
 
        /* clear all status bits */
-       iowrite32(MSGDMA_CSR_STAT_MASK, &txcsr->status);
+       csrwr32(MSGDMA_CSR_STAT_MASK, priv->tx_dma_csr, msgdma_csroffs(status));
 }
 
 void msgdma_disable_rxirq(struct altera_tse_private *priv)
 {
-       struct msgdma_csr *csr = priv->rx_dma_csr;
-       tse_clear_bit(&csr->control, MSGDMA_CSR_CTL_GLOBAL_INTR);
+       tse_clear_bit(priv->rx_dma_csr, msgdma_csroffs(control),
+                     MSGDMA_CSR_CTL_GLOBAL_INTR);
 }
 
 void msgdma_enable_rxirq(struct altera_tse_private *priv)
 {
-       struct msgdma_csr *csr = priv->rx_dma_csr;
-       tse_set_bit(&csr->control, MSGDMA_CSR_CTL_GLOBAL_INTR);
+       tse_set_bit(priv->rx_dma_csr, msgdma_csroffs(control),
+                   MSGDMA_CSR_CTL_GLOBAL_INTR);
 }
 
 void msgdma_disable_txirq(struct altera_tse_private *priv)
 {
-       struct msgdma_csr *csr = priv->tx_dma_csr;
-       tse_clear_bit(&csr->control, MSGDMA_CSR_CTL_GLOBAL_INTR);
+       tse_clear_bit(priv->tx_dma_csr, msgdma_csroffs(control),
+                     MSGDMA_CSR_CTL_GLOBAL_INTR);
 }
 
 void msgdma_enable_txirq(struct altera_tse_private *priv)
 {
-       struct msgdma_csr *csr = priv->tx_dma_csr;
-       tse_set_bit(&csr->control, MSGDMA_CSR_CTL_GLOBAL_INTR);
+       tse_set_bit(priv->tx_dma_csr, msgdma_csroffs(control),
+                   MSGDMA_CSR_CTL_GLOBAL_INTR);
 }
 
 void msgdma_clear_rxirq(struct altera_tse_private *priv)
 {
-       struct msgdma_csr *csr = priv->rx_dma_csr;
-       iowrite32(MSGDMA_CSR_STAT_IRQ, &csr->status);
+       csrwr32(MSGDMA_CSR_STAT_IRQ, priv->rx_dma_csr, msgdma_csroffs(status));
 }
 
 void msgdma_clear_txirq(struct altera_tse_private *priv)
 {
-       struct msgdma_csr *csr = priv->tx_dma_csr;
-       iowrite32(MSGDMA_CSR_STAT_IRQ, &csr->status);
+       csrwr32(MSGDMA_CSR_STAT_IRQ, priv->tx_dma_csr, msgdma_csroffs(status));
 }
 
 /* return 0 to indicate transmit is pending */
 int msgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *buffer)
 {
-       struct msgdma_extended_desc *desc = priv->tx_dma_desc;
-
-       iowrite32(lower_32_bits(buffer->dma_addr), &desc->read_addr_lo);
-       iowrite32(upper_32_bits(buffer->dma_addr), &desc->read_addr_hi);
-       iowrite32(0, &desc->write_addr_lo);
-       iowrite32(0, &desc->write_addr_hi);
-       iowrite32(buffer->len, &desc->len);
-       iowrite32(0, &desc->burst_seq_num);
-       iowrite32(MSGDMA_DESC_TX_STRIDE, &desc->stride);
-       iowrite32(MSGDMA_DESC_CTL_TX_SINGLE, &desc->control);
+       csrwr32(lower_32_bits(buffer->dma_addr), priv->tx_dma_desc,
+               msgdma_descroffs(read_addr_lo));
+       csrwr32(upper_32_bits(buffer->dma_addr), priv->tx_dma_desc,
+               msgdma_descroffs(read_addr_hi));
+       csrwr32(0, priv->tx_dma_desc, msgdma_descroffs(write_addr_lo));
+       csrwr32(0, priv->tx_dma_desc, msgdma_descroffs(write_addr_hi));
+       csrwr32(buffer->len, priv->tx_dma_desc, msgdma_descroffs(len));
+       csrwr32(0, priv->tx_dma_desc, msgdma_descroffs(burst_seq_num));
+       csrwr32(MSGDMA_DESC_TX_STRIDE, priv->tx_dma_desc,
+               msgdma_descroffs(stride));
+       csrwr32(MSGDMA_DESC_CTL_TX_SINGLE, priv->tx_dma_desc,
+               msgdma_descroffs(control));
        return 0;
 }
 
@@ -133,17 +139,16 @@ u32 msgdma_tx_completions(struct altera_tse_private *priv)
        u32 ready = 0;
        u32 inuse;
        u32 status;
-       struct msgdma_csr *txcsr =
-               (struct msgdma_csr *)priv->tx_dma_csr;
 
        /* Get number of sent descriptors */
-       inuse = ioread32(&txcsr->rw_fill_level) & 0xffff;
+       inuse = csrrd32(priv->tx_dma_csr, msgdma_csroffs(rw_fill_level))
+                       & 0xffff;
 
        if (inuse) { /* Tx FIFO is not empty */
                ready = priv->tx_prod - priv->tx_cons - inuse - 1;
        } else {
                /* Check for buffered last packet */
-               status = ioread32(&txcsr->status);
+               status = csrrd32(priv->tx_dma_csr, msgdma_csroffs(status));
                if (status & MSGDMA_CSR_STAT_BUSY)
                        ready = priv->tx_prod - priv->tx_cons - 1;
                else
@@ -154,10 +159,9 @@ u32 msgdma_tx_completions(struct altera_tse_private *priv)
 
 /* Put buffer to the mSGDMA RX FIFO
  */
-int msgdma_add_rx_desc(struct altera_tse_private *priv,
+void msgdma_add_rx_desc(struct altera_tse_private *priv,
                        struct tse_buffer *rxbuffer)
 {
-       struct msgdma_extended_desc *desc = priv->rx_dma_desc;
        u32 len = priv->rx_dma_buf_sz;
        dma_addr_t dma_addr = rxbuffer->dma_addr;
        u32 control = (MSGDMA_DESC_CTL_END_ON_EOP
@@ -167,15 +171,16 @@ int msgdma_add_rx_desc(struct altera_tse_private *priv,
                        | MSGDMA_DESC_CTL_TR_ERR_IRQ
                        | MSGDMA_DESC_CTL_GO);
 
-       iowrite32(0, &desc->read_addr_lo);
-       iowrite32(0, &desc->read_addr_hi);
-       iowrite32(lower_32_bits(dma_addr), &desc->write_addr_lo);
-       iowrite32(upper_32_bits(dma_addr), &desc->write_addr_hi);
-       iowrite32(len, &desc->len);
-       iowrite32(0, &desc->burst_seq_num);
-       iowrite32(0x00010001, &desc->stride);
-       iowrite32(control, &desc->control);
-       return 1;
+       csrwr32(0, priv->rx_dma_desc, msgdma_descroffs(read_addr_lo));
+       csrwr32(0, priv->rx_dma_desc, msgdma_descroffs(read_addr_hi));
+       csrwr32(lower_32_bits(dma_addr), priv->rx_dma_desc,
+               msgdma_descroffs(write_addr_lo));
+       csrwr32(upper_32_bits(dma_addr), priv->rx_dma_desc,
+               msgdma_descroffs(write_addr_hi));
+       csrwr32(len, priv->rx_dma_desc, msgdma_descroffs(len));
+       csrwr32(0, priv->rx_dma_desc, msgdma_descroffs(burst_seq_num));
+       csrwr32(0x00010001, priv->rx_dma_desc, msgdma_descroffs(stride));
+       csrwr32(control, priv->rx_dma_desc, msgdma_descroffs(control));
 }
 
 /* status is returned on upper 16 bits,
@@ -186,14 +191,13 @@ u32 msgdma_rx_status(struct altera_tse_private *priv)
        u32 rxstatus = 0;
        u32 pktlength;
        u32 pktstatus;
-       struct msgdma_csr *rxcsr =
-               (struct msgdma_csr *)priv->rx_dma_csr;
-       struct msgdma_response *rxresp =
-               (struct msgdma_response *)priv->rx_dma_resp;
-
-       if (ioread32(&rxcsr->resp_fill_level) & 0xffff) {
-               pktlength = ioread32(&rxresp->bytes_transferred);
-               pktstatus = ioread32(&rxresp->status);
+
+       if (csrrd32(priv->rx_dma_csr, msgdma_csroffs(resp_fill_level))
+           & 0xffff) {
+               pktlength = csrrd32(priv->rx_dma_resp,
+                                   msgdma_respoffs(bytes_transferred));
+               pktstatus = csrrd32(priv->rx_dma_resp,
+                                   msgdma_respoffs(status));
                rxstatus = pktstatus;
                rxstatus = rxstatus << 16;
                rxstatus |= (pktlength & 0xffff);
index 7f0f5bf2bba2f42952ea69307c44a334f6784b59..42cf61c81057be8f4c3f2213dfdd9e89de7dee15 100644 (file)
@@ -25,10 +25,11 @@ void msgdma_disable_txirq(struct altera_tse_private *);
 void msgdma_clear_rxirq(struct altera_tse_private *);
 void msgdma_clear_txirq(struct altera_tse_private *);
 u32 msgdma_tx_completions(struct altera_tse_private *);
-int msgdma_add_rx_desc(struct altera_tse_private *, struct tse_buffer *);
+void msgdma_add_rx_desc(struct altera_tse_private *, struct tse_buffer *);
 int msgdma_tx_buffer(struct altera_tse_private *, struct tse_buffer *);
 u32 msgdma_rx_status(struct altera_tse_private *);
 int msgdma_initialize(struct altera_tse_private *);
 void msgdma_uninitialize(struct altera_tse_private *);
+void msgdma_start_rxdma(struct altera_tse_private *);
 
 #endif /*  __ALTERA_MSGDMA_H__ */
index d7b59ba4019c1fe1914b2b5c0643e464fcdff62d..e335626e1b6b5288c4f3d4cc8f45d79dcd56655d 100644 (file)
 #ifndef __ALTERA_MSGDMAHW_H__
 #define __ALTERA_MSGDMAHW_H__
 
-/* mSGDMA standard descriptor format
- */
-struct msgdma_desc {
-       u32 read_addr;  /* data buffer source address */
-       u32 write_addr; /* data buffer destination address */
-       u32 len;        /* the number of bytes to transfer per descriptor */
-       u32 control;    /* characteristics of the transfer */
-};
-
 /* mSGDMA extended descriptor format
  */
 struct msgdma_extended_desc {
@@ -159,6 +150,10 @@ struct msgdma_response {
        u32 status;
 };
 
+#define msgdma_respoffs(a) (offsetof(struct msgdma_response, a))
+#define msgdma_csroffs(a) (offsetof(struct msgdma_csr, a))
+#define msgdma_descroffs(a) (offsetof(struct msgdma_extended_desc, a))
+
 /* mSGDMA response register bit definitions
  */
 #define MSGDMA_RESP_EARLY_TERM BIT(8)
index 0ee96639ae44e7a238ac36682868443caa7c43c3..99cc56f451cf4886fbf0a5bca044dfa5cf033a2c 100644 (file)
 #include "altera_sgdmahw.h"
 #include "altera_sgdma.h"
 
-static void sgdma_descrip(struct sgdma_descrip *desc,
-                         struct sgdma_descrip *ndesc,
-                         dma_addr_t ndesc_phys,
-                         dma_addr_t raddr,
-                         dma_addr_t waddr,
-                         u16 length,
-                         int generate_eop,
-                         int rfixed,
-                         int wfixed);
+static void sgdma_setup_descrip(struct sgdma_descrip __iomem *desc,
+                               struct sgdma_descrip __iomem *ndesc,
+                               dma_addr_t ndesc_phys,
+                               dma_addr_t raddr,
+                               dma_addr_t waddr,
+                               u16 length,
+                               int generate_eop,
+                               int rfixed,
+                               int wfixed);
 
 static int sgdma_async_write(struct altera_tse_private *priv,
-                             struct sgdma_descrip *desc);
+                             struct sgdma_descrip __iomem *desc);
 
 static int sgdma_async_read(struct altera_tse_private *priv);
 
 static dma_addr_t
 sgdma_txphysaddr(struct altera_tse_private *priv,
-                struct sgdma_descrip *desc);
+                struct sgdma_descrip __iomem *desc);
 
 static dma_addr_t
 sgdma_rxphysaddr(struct altera_tse_private *priv,
-                struct sgdma_descrip *desc);
+                struct sgdma_descrip __iomem *desc);
 
 static int sgdma_txbusy(struct altera_tse_private *priv);
 
@@ -64,18 +64,23 @@ queue_rx_peekhead(struct altera_tse_private *priv);
 
 int sgdma_initialize(struct altera_tse_private *priv)
 {
-       priv->txctrlreg = SGDMA_CTRLREG_ILASTD;
+       priv->txctrlreg = SGDMA_CTRLREG_ILASTD |
+                     SGDMA_CTRLREG_INTEN;
 
        priv->rxctrlreg = SGDMA_CTRLREG_IDESCRIP |
+                     SGDMA_CTRLREG_INTEN |
                      SGDMA_CTRLREG_ILASTD;
 
+       priv->sgdmadesclen = sizeof(struct sgdma_descrip);
+
        INIT_LIST_HEAD(&priv->txlisthd);
        INIT_LIST_HEAD(&priv->rxlisthd);
 
        priv->rxdescphys = (dma_addr_t) 0;
        priv->txdescphys = (dma_addr_t) 0;
 
-       priv->rxdescphys = dma_map_single(priv->device, priv->rx_dma_desc,
+       priv->rxdescphys = dma_map_single(priv->device,
+                                         (void __force *)priv->rx_dma_desc,
                                          priv->rxdescmem, DMA_BIDIRECTIONAL);
 
        if (dma_mapping_error(priv->device, priv->rxdescphys)) {
@@ -84,7 +89,8 @@ int sgdma_initialize(struct altera_tse_private *priv)
                return -EINVAL;
        }
 
-       priv->txdescphys = dma_map_single(priv->device, priv->tx_dma_desc,
+       priv->txdescphys = dma_map_single(priv->device,
+                                         (void __force *)priv->tx_dma_desc,
                                          priv->txdescmem, DMA_TO_DEVICE);
 
        if (dma_mapping_error(priv->device, priv->txdescphys)) {
@@ -93,6 +99,16 @@ int sgdma_initialize(struct altera_tse_private *priv)
                return -EINVAL;
        }
 
+       /* Initialize descriptor memory to all 0's, sync memory to cache */
+       memset_io(priv->tx_dma_desc, 0, priv->txdescmem);
+       memset_io(priv->rx_dma_desc, 0, priv->rxdescmem);
+
+       dma_sync_single_for_device(priv->device, priv->txdescphys,
+                                  priv->txdescmem, DMA_TO_DEVICE);
+
+       dma_sync_single_for_device(priv->device, priv->rxdescphys,
+                                  priv->rxdescmem, DMA_TO_DEVICE);
+
        return 0;
 }
 
@@ -112,58 +128,48 @@ void sgdma_uninitialize(struct altera_tse_private *priv)
  */
 void sgdma_reset(struct altera_tse_private *priv)
 {
-       u32 *ptxdescripmem = (u32 *)priv->tx_dma_desc;
-       u32 txdescriplen   = priv->txdescmem;
-       u32 *prxdescripmem = (u32 *)priv->rx_dma_desc;
-       u32 rxdescriplen   = priv->rxdescmem;
-       struct sgdma_csr *ptxsgdma = (struct sgdma_csr *)priv->tx_dma_csr;
-       struct sgdma_csr *prxsgdma = (struct sgdma_csr *)priv->rx_dma_csr;
-
        /* Initialize descriptor memory to 0 */
-       memset(ptxdescripmem, 0, txdescriplen);
-       memset(prxdescripmem, 0, rxdescriplen);
+       memset_io(priv->tx_dma_desc, 0, priv->txdescmem);
+       memset_io(priv->rx_dma_desc, 0, priv->rxdescmem);
 
-       iowrite32(SGDMA_CTRLREG_RESET, &ptxsgdma->control);
-       iowrite32(0, &ptxsgdma->control);
+       csrwr32(SGDMA_CTRLREG_RESET, priv->tx_dma_csr, sgdma_csroffs(control));
+       csrwr32(0, priv->tx_dma_csr, sgdma_csroffs(control));
 
-       iowrite32(SGDMA_CTRLREG_RESET, &prxsgdma->control);
-       iowrite32(0, &prxsgdma->control);
+       csrwr32(SGDMA_CTRLREG_RESET, priv->rx_dma_csr, sgdma_csroffs(control));
+       csrwr32(0, priv->rx_dma_csr, sgdma_csroffs(control));
 }
 
+/* For SGDMA, interrupts remain enabled after initially enabling,
+ * so no need to provide implementations for abstract enable
+ * and disable
+ */
+
 void sgdma_enable_rxirq(struct altera_tse_private *priv)
 {
-       struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr;
-       priv->rxctrlreg |= SGDMA_CTRLREG_INTEN;
-       tse_set_bit(&csr->control, SGDMA_CTRLREG_INTEN);
 }
 
 void sgdma_enable_txirq(struct altera_tse_private *priv)
 {
-       struct sgdma_csr *csr = (struct sgdma_csr *)priv->tx_dma_csr;
-       priv->txctrlreg |= SGDMA_CTRLREG_INTEN;
-       tse_set_bit(&csr->control, SGDMA_CTRLREG_INTEN);
 }
 
-/* for SGDMA, RX interrupts remain enabled after enabling */
 void sgdma_disable_rxirq(struct altera_tse_private *priv)
 {
 }
 
-/* for SGDMA, TX interrupts remain enabled after enabling */
 void sgdma_disable_txirq(struct altera_tse_private *priv)
 {
 }
 
 void sgdma_clear_rxirq(struct altera_tse_private *priv)
 {
-       struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr;
-       tse_set_bit(&csr->control, SGDMA_CTRLREG_CLRINT);
+       tse_set_bit(priv->rx_dma_csr, sgdma_csroffs(control),
+                   SGDMA_CTRLREG_CLRINT);
 }
 
 void sgdma_clear_txirq(struct altera_tse_private *priv)
 {
-       struct sgdma_csr *csr = (struct sgdma_csr *)priv->tx_dma_csr;
-       tse_set_bit(&csr->control, SGDMA_CTRLREG_CLRINT);
+       tse_set_bit(priv->tx_dma_csr, sgdma_csroffs(control),
+                   SGDMA_CTRLREG_CLRINT);
 }
 
 /* transmits buffer through SGDMA. Returns number of buffers
@@ -173,28 +179,27 @@ void sgdma_clear_txirq(struct altera_tse_private *priv)
  */
 int sgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *buffer)
 {
-       int pktstx = 0;
-       struct sgdma_descrip *descbase =
-               (struct sgdma_descrip *)priv->tx_dma_desc;
+       struct sgdma_descrip __iomem *descbase =
+               (struct sgdma_descrip __iomem *)priv->tx_dma_desc;
 
-       struct sgdma_descrip *cdesc = &descbase[0];
-       struct sgdma_descrip *ndesc = &descbase[1];
+       struct sgdma_descrip __iomem *cdesc = &descbase[0];
+       struct sgdma_descrip __iomem *ndesc = &descbase[1];
 
        /* wait 'til the tx sgdma is ready for the next transmit request */
        if (sgdma_txbusy(priv))
                return 0;
 
-       sgdma_descrip(cdesc,                    /* current descriptor */
-                     ndesc,                    /* next descriptor */
-                     sgdma_txphysaddr(priv, ndesc),
-                     buffer->dma_addr,         /* address of packet to xmit */
-                     0,                        /* write addr 0 for tx dma */
-                     buffer->len,              /* length of packet */
-                     SGDMA_CONTROL_EOP,        /* Generate EOP */
-                     0,                        /* read fixed */
-                     SGDMA_CONTROL_WR_FIXED);  /* Generate SOP */
+       sgdma_setup_descrip(cdesc,                      /* current descriptor */
+                           ndesc,                      /* next descriptor */
+                           sgdma_txphysaddr(priv, ndesc),
+                           buffer->dma_addr,           /* address of packet to xmit */
+                           0,                          /* write addr 0 for tx dma */
+                           buffer->len,                /* length of packet */
+                           SGDMA_CONTROL_EOP,          /* Generate EOP */
+                           0,                          /* read fixed */
+                           SGDMA_CONTROL_WR_FIXED);    /* Generate SOP */
 
-       pktstx = sgdma_async_write(priv, cdesc);
+       sgdma_async_write(priv, cdesc);
 
        /* enqueue the request to the pending transmit queue */
        queue_tx(priv, buffer);
@@ -208,10 +213,10 @@ int sgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *buffer)
 u32 sgdma_tx_completions(struct altera_tse_private *priv)
 {
        u32 ready = 0;
-       struct sgdma_descrip *desc = (struct sgdma_descrip *)priv->tx_dma_desc;
 
        if (!sgdma_txbusy(priv) &&
-           ((desc->control & SGDMA_CONTROL_HW_OWNED) == 0) &&
+           ((csrrd8(priv->tx_dma_desc, sgdma_descroffs(control))
+            & SGDMA_CONTROL_HW_OWNED) == 0) &&
            (dequeue_tx(priv))) {
                ready = 1;
        }
@@ -219,11 +224,15 @@ u32 sgdma_tx_completions(struct altera_tse_private *priv)
        return ready;
 }
 
-int sgdma_add_rx_desc(struct altera_tse_private *priv,
-                     struct tse_buffer *rxbuffer)
+void sgdma_start_rxdma(struct altera_tse_private *priv)
+{
+       sgdma_async_read(priv);
+}
+
+void sgdma_add_rx_desc(struct altera_tse_private *priv,
+                      struct tse_buffer *rxbuffer)
 {
        queue_rx(priv, rxbuffer);
-       return sgdma_async_read(priv);
 }
 
 /* status is returned on upper 16 bits,
@@ -231,38 +240,62 @@ int sgdma_add_rx_desc(struct altera_tse_private *priv,
  */
 u32 sgdma_rx_status(struct altera_tse_private *priv)
 {
-       struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr;
-       struct sgdma_descrip *base = (struct sgdma_descrip *)priv->rx_dma_desc;
-       struct sgdma_descrip *desc = NULL;
-       int pktsrx;
-       unsigned int rxstatus = 0;
-       unsigned int pktlength = 0;
-       unsigned int pktstatus = 0;
+       struct sgdma_descrip __iomem *base =
+               (struct sgdma_descrip __iomem *)priv->rx_dma_desc;
+       struct sgdma_descrip __iomem *desc = NULL;
        struct tse_buffer *rxbuffer = NULL;
+       unsigned int rxstatus = 0;
 
-       dma_sync_single_for_cpu(priv->device,
-                               priv->rxdescphys,
-                               priv->rxdescmem,
-                               DMA_BIDIRECTIONAL);
+       u32 sts = csrrd32(priv->rx_dma_csr, sgdma_csroffs(status));
 
        desc = &base[0];
-       if ((ioread32(&csr->status) & SGDMA_STSREG_EOP) ||
-           (desc->status & SGDMA_STATUS_EOP)) {
-               pktlength = desc->bytes_xferred;
-               pktstatus = desc->status & 0x3f;
-               rxstatus = pktstatus;
+       if (sts & SGDMA_STSREG_EOP) {
+               unsigned int pktlength = 0;
+               unsigned int pktstatus = 0;
+               dma_sync_single_for_cpu(priv->device,
+                                       priv->rxdescphys,
+                                       priv->sgdmadesclen,
+                                       DMA_FROM_DEVICE);
+
+               pktlength = csrrd16(desc, sgdma_descroffs(bytes_xferred));
+               pktstatus = csrrd8(desc, sgdma_descroffs(status));
+               rxstatus = pktstatus & ~SGDMA_STATUS_EOP;
                rxstatus = rxstatus << 16;
                rxstatus |= (pktlength & 0xffff);
 
-               desc->status = 0;
-
-               rxbuffer = dequeue_rx(priv);
-               if (rxbuffer == NULL)
+               if (rxstatus) {
+                       csrwr8(0, desc, sgdma_descroffs(status));
+
+                       rxbuffer = dequeue_rx(priv);
+                       if (rxbuffer == NULL)
+                               netdev_info(priv->dev,
+                                           "sgdma rx and rx queue empty!\n");
+
+                       /* Clear control */
+                       csrwr32(0, priv->rx_dma_csr, sgdma_csroffs(control));
+                       /* clear status */
+                       csrwr32(0xf, priv->rx_dma_csr, sgdma_csroffs(status));
+
+                       /* kick the rx sgdma after reaping this descriptor */
+                       sgdma_async_read(priv);
+
+               } else {
+                       /* If the SGDMA indicated an end of packet on recv,
+                        * then it's expected that the rxstatus from the
+                        * descriptor is non-zero - meaning a valid packet
+                        * with a nonzero length, or an error has been
+                        * indicated. if not, then all we can do is signal
+                        * an error and return no packet received. Most likely
+                        * there is a system design error, or an error in the
+                        * underlying kernel (cache or cache management problem)
+                        */
                        netdev_err(priv->dev,
-                                  "sgdma rx and rx queue empty!\n");
-
-               /* kick the rx sgdma after reaping this descriptor */
-               pktsrx = sgdma_async_read(priv);
+                                  "SGDMA RX Error Info: %x, %x, %x\n",
+                                  sts, csrrd8(desc, sgdma_descroffs(status)),
+                                  rxstatus);
+               }
+       } else if (sts == 0) {
+               sgdma_async_read(priv);
        }
 
        return rxstatus;
@@ -270,38 +303,41 @@ u32 sgdma_rx_status(struct altera_tse_private *priv)
 
 
 /* Private functions */
-static void sgdma_descrip(struct sgdma_descrip *desc,
-                         struct sgdma_descrip *ndesc,
-                         dma_addr_t ndesc_phys,
-                         dma_addr_t raddr,
-                         dma_addr_t waddr,
-                         u16 length,
-                         int generate_eop,
-                         int rfixed,
-                         int wfixed)
+static void sgdma_setup_descrip(struct sgdma_descrip __iomem *desc,
+                               struct sgdma_descrip __iomem *ndesc,
+                               dma_addr_t ndesc_phys,
+                               dma_addr_t raddr,
+                               dma_addr_t waddr,
+                               u16 length,
+                               int generate_eop,
+                               int rfixed,
+                               int wfixed)
 {
        /* Clear the next descriptor as not owned by hardware */
-       u32 ctrl = ndesc->control;
+
+       u32 ctrl = csrrd8(ndesc, sgdma_descroffs(control));
        ctrl &= ~SGDMA_CONTROL_HW_OWNED;
-       ndesc->control = ctrl;
+       csrwr8(ctrl, ndesc, sgdma_descroffs(control));
 
-       ctrl = 0;
        ctrl = SGDMA_CONTROL_HW_OWNED;
        ctrl |= generate_eop;
        ctrl |= rfixed;
        ctrl |= wfixed;
 
        /* Channel is implicitly zero, initialized to 0 by default */
-
-       desc->raddr = raddr;
-       desc->waddr = waddr;
-       desc->next = lower_32_bits(ndesc_phys);
-       desc->control = ctrl;
-       desc->status = 0;
-       desc->rburst = 0;
-       desc->wburst = 0;
-       desc->bytes = length;
-       desc->bytes_xferred = 0;
+       csrwr32(lower_32_bits(raddr), desc, sgdma_descroffs(raddr));
+       csrwr32(lower_32_bits(waddr), desc, sgdma_descroffs(waddr));
+
+       csrwr32(0, desc, sgdma_descroffs(pad1));
+       csrwr32(0, desc, sgdma_descroffs(pad2));
+       csrwr32(lower_32_bits(ndesc_phys), desc, sgdma_descroffs(next));
+
+       csrwr8(ctrl, desc, sgdma_descroffs(control));
+       csrwr8(0, desc, sgdma_descroffs(status));
+       csrwr8(0, desc, sgdma_descroffs(wburst));
+       csrwr8(0, desc, sgdma_descroffs(rburst));
+       csrwr16(length, desc, sgdma_descroffs(bytes));
+       csrwr16(0, desc, sgdma_descroffs(bytes_xferred));
 }
 
 /* If hardware is busy, don't restart async read.
@@ -312,48 +348,43 @@ static void sgdma_descrip(struct sgdma_descrip *desc,
  */
 static int sgdma_async_read(struct altera_tse_private *priv)
 {
-       struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr;
-       struct sgdma_descrip *descbase =
-               (struct sgdma_descrip *)priv->rx_dma_desc;
+       struct sgdma_descrip __iomem *descbase =
+               (struct sgdma_descrip __iomem *)priv->rx_dma_desc;
 
-       struct sgdma_descrip *cdesc = &descbase[0];
-       struct sgdma_descrip *ndesc = &descbase[1];
+       struct sgdma_descrip __iomem *cdesc = &descbase[0];
+       struct sgdma_descrip __iomem *ndesc = &descbase[1];
 
-       unsigned int sts = ioread32(&csr->status);
        struct tse_buffer *rxbuffer = NULL;
 
        if (!sgdma_rxbusy(priv)) {
                rxbuffer = queue_rx_peekhead(priv);
-               if (rxbuffer == NULL)
+               if (rxbuffer == NULL) {
+                       netdev_err(priv->dev, "no rx buffers available\n");
                        return 0;
-
-               sgdma_descrip(cdesc,            /* current descriptor */
-                             ndesc,            /* next descriptor */
-                             sgdma_rxphysaddr(priv, ndesc),
-                             0,                /* read addr 0 for rx dma */
-                             rxbuffer->dma_addr, /* write addr for rx dma */
-                             0,                /* read 'til EOP */
-                             0,                /* EOP: NA for rx dma */
-                             0,                /* read fixed: NA for rx dma */
-                             0);               /* SOP: NA for rx DMA */
-
-               /* clear control and status */
-               iowrite32(0, &csr->control);
-
-               /* If status available, clear those bits */
-               if (sts & 0xf)
-                       iowrite32(0xf, &csr->status);
+               }
+
+               sgdma_setup_descrip(cdesc,              /* current descriptor */
+                                   ndesc,              /* next descriptor */
+                                   sgdma_rxphysaddr(priv, ndesc),
+                                   0,                  /* read addr 0 for rx dma */
+                                   rxbuffer->dma_addr, /* write addr for rx dma */
+                                   0,                  /* read 'til EOP */
+                                   0,                  /* EOP: NA for rx dma */
+                                   0,                  /* read fixed: NA for rx dma */
+                                   0);                 /* SOP: NA for rx DMA */
 
                dma_sync_single_for_device(priv->device,
                                           priv->rxdescphys,
-                                          priv->rxdescmem,
-                                          DMA_BIDIRECTIONAL);
+                                          priv->sgdmadesclen,
+                                          DMA_TO_DEVICE);
 
-               iowrite32(lower_32_bits(sgdma_rxphysaddr(priv, cdesc)),
-                         &csr->next_descrip);
+               csrwr32(lower_32_bits(sgdma_rxphysaddr(priv, cdesc)),
+                       priv->rx_dma_csr,
+                       sgdma_csroffs(next_descrip));
 
-               iowrite32((priv->rxctrlreg | SGDMA_CTRLREG_START),
-                         &csr->control);
+               csrwr32((priv->rxctrlreg | SGDMA_CTRLREG_START),
+                       priv->rx_dma_csr,
+                       sgdma_csroffs(control));
 
                return 1;
        }
@@ -362,32 +393,32 @@ static int sgdma_async_read(struct altera_tse_private *priv)
 }
 
 static int sgdma_async_write(struct altera_tse_private *priv,
-                            struct sgdma_descrip *desc)
+                            struct sgdma_descrip __iomem *desc)
 {
-       struct sgdma_csr *csr = (struct sgdma_csr *)priv->tx_dma_csr;
-
        if (sgdma_txbusy(priv))
                return 0;
 
        /* clear control and status */
-       iowrite32(0, &csr->control);
-       iowrite32(0x1f, &csr->status);
+       csrwr32(0, priv->tx_dma_csr, sgdma_csroffs(control));
+       csrwr32(0x1f, priv->tx_dma_csr, sgdma_csroffs(status));
 
        dma_sync_single_for_device(priv->device, priv->txdescphys,
-                                  priv->txdescmem, DMA_TO_DEVICE);
+                                  priv->sgdmadesclen, DMA_TO_DEVICE);
 
-       iowrite32(lower_32_bits(sgdma_txphysaddr(priv, desc)),
-                 &csr->next_descrip);
+       csrwr32(lower_32_bits(sgdma_txphysaddr(priv, desc)),
+               priv->tx_dma_csr,
+               sgdma_csroffs(next_descrip));
 
-       iowrite32((priv->txctrlreg | SGDMA_CTRLREG_START),
-                 &csr->control);
+       csrwr32((priv->txctrlreg | SGDMA_CTRLREG_START),
+               priv->tx_dma_csr,
+               sgdma_csroffs(control));
 
        return 1;
 }
 
 static dma_addr_t
 sgdma_txphysaddr(struct altera_tse_private *priv,
-                struct sgdma_descrip *desc)
+                struct sgdma_descrip __iomem *desc)
 {
        dma_addr_t paddr = priv->txdescmem_busaddr;
        uintptr_t offs = (uintptr_t)desc - (uintptr_t)priv->tx_dma_desc;
@@ -396,7 +427,7 @@ sgdma_txphysaddr(struct altera_tse_private *priv,
 
 static dma_addr_t
 sgdma_rxphysaddr(struct altera_tse_private *priv,
-                struct sgdma_descrip *desc)
+                struct sgdma_descrip __iomem *desc)
 {
        dma_addr_t paddr = priv->rxdescmem_busaddr;
        uintptr_t offs = (uintptr_t)desc - (uintptr_t)priv->rx_dma_desc;
@@ -485,8 +516,8 @@ queue_rx_peekhead(struct altera_tse_private *priv)
  */
 static int sgdma_rxbusy(struct altera_tse_private *priv)
 {
-       struct sgdma_csr *csr = (struct sgdma_csr *)priv->rx_dma_csr;
-       return ioread32(&csr->status) & SGDMA_STSREG_BUSY;
+       return csrrd32(priv->rx_dma_csr, sgdma_csroffs(status))
+                      & SGDMA_STSREG_BUSY;
 }
 
 /* waits for the tx sgdma to finish it's current operation, returns 0
@@ -495,13 +526,14 @@ static int sgdma_rxbusy(struct altera_tse_private *priv)
 static int sgdma_txbusy(struct altera_tse_private *priv)
 {
        int delay = 0;
-       struct sgdma_csr *csr = (struct sgdma_csr *)priv->tx_dma_csr;
 
        /* if DMA is busy, wait for current transactino to finish */
-       while ((ioread32(&csr->status) & SGDMA_STSREG_BUSY) && (delay++ < 100))
+       while ((csrrd32(priv->tx_dma_csr, sgdma_csroffs(status))
+               & SGDMA_STSREG_BUSY) && (delay++ < 100))
                udelay(1);
 
-       if (ioread32(&csr->status) & SGDMA_STSREG_BUSY) {
+       if (csrrd32(priv->tx_dma_csr, sgdma_csroffs(status))
+           & SGDMA_STSREG_BUSY) {
                netdev_err(priv->dev, "timeout waiting for tx dma\n");
                return 1;
        }
index 07d471729dc4978deee7fc592962999ec1eff1f3..584977e29ef944e1132f3ec779d7cdf1f9572160 100644 (file)
@@ -26,10 +26,11 @@ void sgdma_clear_rxirq(struct altera_tse_private *);
 void sgdma_clear_txirq(struct altera_tse_private *);
 int sgdma_tx_buffer(struct altera_tse_private *priv, struct tse_buffer *);
 u32 sgdma_tx_completions(struct altera_tse_private *);
-int sgdma_add_rx_desc(struct altera_tse_private *priv, struct tse_buffer *);
+void sgdma_add_rx_desc(struct altera_tse_private *priv, struct tse_buffer *);
 void sgdma_status(struct altera_tse_private *);
 u32 sgdma_rx_status(struct altera_tse_private *);
 int sgdma_initialize(struct altera_tse_private *);
 void sgdma_uninitialize(struct altera_tse_private *);
+void sgdma_start_rxdma(struct altera_tse_private *);
 
 #endif /*  __ALTERA_SGDMA_H__ */
index ba3334f353836cd0441d537ba5fda8a28bea171e..85bc33b218d946f557647d1a73f9699e3189827b 100644 (file)
 
 /* SGDMA descriptor structure */
 struct sgdma_descrip {
-       unsigned int    raddr; /* address of data to be read */
-       unsigned int    pad1;
-       unsigned int    waddr;
-       unsigned int    pad2;
-       unsigned int    next;
-       unsigned int    pad3;
-       unsigned short  bytes;
-       unsigned char   rburst;
-       unsigned char   wburst;
-       unsigned short  bytes_xferred;  /* 16 bits, bytes xferred */
+       u32     raddr; /* address of data to be read */
+       u32     pad1;
+       u32     waddr;
+       u32     pad2;
+       u32     next;
+       u32     pad3;
+       u16     bytes;
+       u8      rburst;
+       u8      wburst;
+       u16     bytes_xferred;  /* 16 bits, bytes xferred */
 
        /* bit 0: error
         * bit 1: length error
@@ -39,7 +39,7 @@ struct sgdma_descrip {
         * bit 6: reserved
         * bit 7: status eop for recv case
         */
-       unsigned char   status;
+       u8      status;
 
        /* bit 0: eop
         * bit 1: read_fixed
@@ -47,7 +47,7 @@ struct sgdma_descrip {
         * bits 3,4,5,6: Channel (always 0)
         * bit 7: hardware owned
         */
-       unsigned char   control;
+       u8      control;
 } __packed;
 
 
@@ -101,6 +101,8 @@ struct sgdma_csr {
        u32     pad3[3];
 };
 
+#define sgdma_csroffs(a) (offsetof(struct sgdma_csr, a))
+#define sgdma_descroffs(a) (offsetof(struct sgdma_descrip, a))
 
 #define SGDMA_STSREG_ERR       BIT(0) /* Error */
 #define SGDMA_STSREG_EOP       BIT(1) /* EOP */
index 8feeed05de0e14829718a1bec85fbb94af6699e6..2adb24d4523c915d3b7d87f1294ead36757cea50 100644 (file)
@@ -58,6 +58,8 @@
 /* MAC function configuration default settings */
 #define ALTERA_TSE_TX_IPG_LENGTH       12
 
+#define ALTERA_TSE_PAUSE_QUANTA                0xffff
+
 #define GET_BIT_VALUE(v, bit)          (((v) >> (bit)) & 0x1)
 
 /* MAC Command_Config Register Bit Definitions
@@ -355,6 +357,8 @@ struct altera_tse_mac {
        u32 reserved5[42];
 };
 
+#define tse_csroffs(a) (offsetof(struct altera_tse_mac, a))
+
 /* Transmit and Receive Command Registers Bit Definitions
  */
 #define ALTERA_TSE_TX_CMD_STAT_OMIT_CRC                BIT(17)
@@ -390,10 +394,11 @@ struct altera_dmaops {
        void (*clear_rxirq)(struct altera_tse_private *);
        int (*tx_buffer)(struct altera_tse_private *, struct tse_buffer *);
        u32 (*tx_completions)(struct altera_tse_private *);
-       int (*add_rx_desc)(struct altera_tse_private *, struct tse_buffer *);
+       void (*add_rx_desc)(struct altera_tse_private *, struct tse_buffer *);
        u32 (*get_rx_status)(struct altera_tse_private *);
        int (*init_dma)(struct altera_tse_private *);
        void (*uninit_dma)(struct altera_tse_private *);
+       void (*start_rxdma)(struct altera_tse_private *);
 };
 
 /* This structure is private to each device.
@@ -453,6 +458,7 @@ struct altera_tse_private {
        u32 rxctrlreg;
        dma_addr_t rxdescphys;
        dma_addr_t txdescphys;
+       size_t sgdmadesclen;
 
        struct list_head txlisthd;
        struct list_head rxlisthd;
@@ -483,4 +489,49 @@ struct altera_tse_private {
  */
 void altera_tse_set_ethtool_ops(struct net_device *);
 
+static inline
+u32 csrrd32(void __iomem *mac, size_t offs)
+{
+       void __iomem *paddr = (void __iomem *)((uintptr_t)mac + offs);
+       return readl(paddr);
+}
+
+static inline
+u16 csrrd16(void __iomem *mac, size_t offs)
+{
+       void __iomem *paddr = (void __iomem *)((uintptr_t)mac + offs);
+       return readw(paddr);
+}
+
+static inline
+u8 csrrd8(void __iomem *mac, size_t offs)
+{
+       void __iomem *paddr = (void __iomem *)((uintptr_t)mac + offs);
+       return readb(paddr);
+}
+
+static inline
+void csrwr32(u32 val, void __iomem *mac, size_t offs)
+{
+       void __iomem *paddr = (void __iomem *)((uintptr_t)mac + offs);
+
+       writel(val, paddr);
+}
+
+static inline
+void csrwr16(u16 val, void __iomem *mac, size_t offs)
+{
+       void __iomem *paddr = (void __iomem *)((uintptr_t)mac + offs);
+
+       writew(val, paddr);
+}
+
+static inline
+void csrwr8(u8 val, void __iomem *mac, size_t offs)
+{
+       void __iomem *paddr = (void __iomem *)((uintptr_t)mac + offs);
+
+       writeb(val, paddr);
+}
+
 #endif /* __ALTERA_TSE_H__ */
index 319ca74f5e7480b23bc0ce63f9dca0a25ce894b2..54c25eff795272661e2caabfd554ffcc7dd24e00 100644 (file)
@@ -77,7 +77,7 @@ static void tse_get_drvinfo(struct net_device *dev,
        struct altera_tse_private *priv = netdev_priv(dev);
        u32 rev = ioread32(&priv->mac_dev->megacore_revision);
 
-       strcpy(info->driver, "Altera TSE MAC IP Driver");
+       strcpy(info->driver, "altera_tse");
        strcpy(info->version, "v8.0");
        snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "v%d.%d",
                 rev & 0xFFFF, (rev & 0xFFFF0000) >> 16);
@@ -96,54 +96,89 @@ static void tse_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
                           u64 *buf)
 {
        struct altera_tse_private *priv = netdev_priv(dev);
-       struct altera_tse_mac *mac = priv->mac_dev;
        u64 ext;
 
-       buf[0] = ioread32(&mac->frames_transmitted_ok);
-       buf[1] = ioread32(&mac->frames_received_ok);
-       buf[2] = ioread32(&mac->frames_check_sequence_errors);
-       buf[3] = ioread32(&mac->alignment_errors);
+       buf[0] = csrrd32(priv->mac_dev,
+                        tse_csroffs(frames_transmitted_ok));
+       buf[1] = csrrd32(priv->mac_dev,
+                        tse_csroffs(frames_received_ok));
+       buf[2] = csrrd32(priv->mac_dev,
+                        tse_csroffs(frames_check_sequence_errors));
+       buf[3] = csrrd32(priv->mac_dev,
+                        tse_csroffs(alignment_errors));
 
        /* Extended aOctetsTransmittedOK counter */
-       ext = (u64) ioread32(&mac->msb_octets_transmitted_ok) << 32;
-       ext |= ioread32(&mac->octets_transmitted_ok);
+       ext = (u64) csrrd32(priv->mac_dev,
+                           tse_csroffs(msb_octets_transmitted_ok)) << 32;
+
+       ext |= csrrd32(priv->mac_dev,
+                      tse_csroffs(octets_transmitted_ok));
        buf[4] = ext;
 
        /* Extended aOctetsReceivedOK counter */
-       ext = (u64) ioread32(&mac->msb_octets_received_ok) << 32;
-       ext |= ioread32(&mac->octets_received_ok);
+       ext = (u64) csrrd32(priv->mac_dev,
+                           tse_csroffs(msb_octets_received_ok)) << 32;
+
+       ext |= csrrd32(priv->mac_dev,
+                      tse_csroffs(octets_received_ok));
        buf[5] = ext;
 
-       buf[6] = ioread32(&mac->tx_pause_mac_ctrl_frames);
-       buf[7] = ioread32(&mac->rx_pause_mac_ctrl_frames);
-       buf[8] = ioread32(&mac->if_in_errors);
-       buf[9] = ioread32(&mac->if_out_errors);
-       buf[10] = ioread32(&mac->if_in_ucast_pkts);
-       buf[11] = ioread32(&mac->if_in_multicast_pkts);
-       buf[12] = ioread32(&mac->if_in_broadcast_pkts);
-       buf[13] = ioread32(&mac->if_out_discards);
-       buf[14] = ioread32(&mac->if_out_ucast_pkts);
-       buf[15] = ioread32(&mac->if_out_multicast_pkts);
-       buf[16] = ioread32(&mac->if_out_broadcast_pkts);
-       buf[17] = ioread32(&mac->ether_stats_drop_events);
+       buf[6] = csrrd32(priv->mac_dev,
+                        tse_csroffs(tx_pause_mac_ctrl_frames));
+       buf[7] = csrrd32(priv->mac_dev,
+                        tse_csroffs(rx_pause_mac_ctrl_frames));
+       buf[8] = csrrd32(priv->mac_dev,
+                        tse_csroffs(if_in_errors));
+       buf[9] = csrrd32(priv->mac_dev,
+                        tse_csroffs(if_out_errors));
+       buf[10] = csrrd32(priv->mac_dev,
+                         tse_csroffs(if_in_ucast_pkts));
+       buf[11] = csrrd32(priv->mac_dev,
+                         tse_csroffs(if_in_multicast_pkts));
+       buf[12] = csrrd32(priv->mac_dev,
+                         tse_csroffs(if_in_broadcast_pkts));
+       buf[13] = csrrd32(priv->mac_dev,
+                         tse_csroffs(if_out_discards));
+       buf[14] = csrrd32(priv->mac_dev,
+                         tse_csroffs(if_out_ucast_pkts));
+       buf[15] = csrrd32(priv->mac_dev,
+                         tse_csroffs(if_out_multicast_pkts));
+       buf[16] = csrrd32(priv->mac_dev,
+                         tse_csroffs(if_out_broadcast_pkts));
+       buf[17] = csrrd32(priv->mac_dev,
+                         tse_csroffs(ether_stats_drop_events));
 
        /* Extended etherStatsOctets counter */
-       ext = (u64) ioread32(&mac->msb_ether_stats_octets) << 32;
-       ext |= ioread32(&mac->ether_stats_octets);
+       ext = (u64) csrrd32(priv->mac_dev,
+                           tse_csroffs(msb_ether_stats_octets)) << 32;
+       ext |= csrrd32(priv->mac_dev,
+                      tse_csroffs(ether_stats_octets));
        buf[18] = ext;
 
-       buf[19] = ioread32(&mac->ether_stats_pkts);
-       buf[20] = ioread32(&mac->ether_stats_undersize_pkts);
-       buf[21] = ioread32(&mac->ether_stats_oversize_pkts);
-       buf[22] = ioread32(&mac->ether_stats_pkts_64_octets);
-       buf[23] = ioread32(&mac->ether_stats_pkts_65to127_octets);
-       buf[24] = ioread32(&mac->ether_stats_pkts_128to255_octets);
-       buf[25] = ioread32(&mac->ether_stats_pkts_256to511_octets);
-       buf[26] = ioread32(&mac->ether_stats_pkts_512to1023_octets);
-       buf[27] = ioread32(&mac->ether_stats_pkts_1024to1518_octets);
-       buf[28] = ioread32(&mac->ether_stats_pkts_1519tox_octets);
-       buf[29] = ioread32(&mac->ether_stats_jabbers);
-       buf[30] = ioread32(&mac->ether_stats_fragments);
+       buf[19] = csrrd32(priv->mac_dev,
+                         tse_csroffs(ether_stats_pkts));
+       buf[20] = csrrd32(priv->mac_dev,
+                         tse_csroffs(ether_stats_undersize_pkts));
+       buf[21] = csrrd32(priv->mac_dev,
+                         tse_csroffs(ether_stats_oversize_pkts));
+       buf[22] = csrrd32(priv->mac_dev,
+                         tse_csroffs(ether_stats_pkts_64_octets));
+       buf[23] = csrrd32(priv->mac_dev,
+                         tse_csroffs(ether_stats_pkts_65to127_octets));
+       buf[24] = csrrd32(priv->mac_dev,
+                         tse_csroffs(ether_stats_pkts_128to255_octets));
+       buf[25] = csrrd32(priv->mac_dev,
+                         tse_csroffs(ether_stats_pkts_256to511_octets));
+       buf[26] = csrrd32(priv->mac_dev,
+                         tse_csroffs(ether_stats_pkts_512to1023_octets));
+       buf[27] = csrrd32(priv->mac_dev,
+                         tse_csroffs(ether_stats_pkts_1024to1518_octets));
+       buf[28] = csrrd32(priv->mac_dev,
+                         tse_csroffs(ether_stats_pkts_1519tox_octets));
+       buf[29] = csrrd32(priv->mac_dev,
+                         tse_csroffs(ether_stats_jabbers));
+       buf[30] = csrrd32(priv->mac_dev,
+                         tse_csroffs(ether_stats_fragments));
 }
 
 static int tse_sset_count(struct net_device *dev, int sset)
@@ -178,19 +213,24 @@ static void tse_get_regs(struct net_device *dev, struct ethtool_regs *regs,
 {
        int i;
        struct altera_tse_private *priv = netdev_priv(dev);
-       u32 *tse_mac_regs = (u32 *)priv->mac_dev;
        u32 *buf = regbuf;
 
        /* Set version to a known value, so ethtool knows
         * how to do any special formatting of this data.
         * This version number will need to change if and
         * when this register table is changed.
+        *
+        * version[31:0] = 1: Dump the first 128 TSE Registers
+        *      Upper bits are all 0 by default
+        *
+        * Upper 16-bits will indicate feature presence for
+        * Ethtool register decoding in future version.
         */
 
        regs->version = 1;
 
        for (i = 0; i < TSE_NUM_REGS; i++)
-               buf[i] = ioread32(&tse_mac_regs[i]);
+               buf[i] = csrrd32(priv->mac_dev, i * 4);
 }
 
 static int tse_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
index c70a29e0b9f79115cc697df95b52757830651ea3..7330681574d20ccd02855beabedc9b01c8ae2b48 100644 (file)
@@ -100,29 +100,30 @@ static inline u32 tse_tx_avail(struct altera_tse_private *priv)
  */
 static int altera_tse_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
 {
-       struct altera_tse_mac *mac = (struct altera_tse_mac *)bus->priv;
-       unsigned int *mdio_regs = (unsigned int *)&mac->mdio_phy0;
-       u32 data;
+       struct net_device *ndev = bus->priv;
+       struct altera_tse_private *priv = netdev_priv(ndev);
 
        /* set MDIO address */
-       iowrite32((mii_id & 0x1f), &mac->mdio_phy0_addr);
+       csrwr32((mii_id & 0x1f), priv->mac_dev,
+               tse_csroffs(mdio_phy0_addr));
 
        /* get the data */
-       data = ioread32(&mdio_regs[regnum]) & 0xffff;
-       return data;
+       return csrrd32(priv->mac_dev,
+                      tse_csroffs(mdio_phy0) + regnum * 4) & 0xffff;
 }
 
 static int altera_tse_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
                                 u16 value)
 {
-       struct altera_tse_mac *mac = (struct altera_tse_mac *)bus->priv;
-       unsigned int *mdio_regs = (unsigned int *)&mac->mdio_phy0;
+       struct net_device *ndev = bus->priv;
+       struct altera_tse_private *priv = netdev_priv(ndev);
 
        /* set MDIO address */
-       iowrite32((mii_id & 0x1f), &mac->mdio_phy0_addr);
+       csrwr32((mii_id & 0x1f), priv->mac_dev,
+               tse_csroffs(mdio_phy0_addr));
 
        /* write the data */
-       iowrite32((u32) value, &mdio_regs[regnum]);
+       csrwr32(value, priv->mac_dev, tse_csroffs(mdio_phy0) + regnum * 4);
        return 0;
 }
 
@@ -168,7 +169,7 @@ static int altera_tse_mdio_create(struct net_device *dev, unsigned int id)
        for (i = 0; i < PHY_MAX_ADDR; i++)
                mdio->irq[i] = PHY_POLL;
 
-       mdio->priv = priv->mac_dev;
+       mdio->priv = dev;
        mdio->parent = priv->device;
 
        ret = of_mdiobus_register(mdio, mdio_node);
@@ -224,6 +225,7 @@ static int tse_init_rx_buffer(struct altera_tse_private *priv,
                dev_kfree_skb_any(rxbuffer->skb);
                return -EINVAL;
        }
+       rxbuffer->dma_addr &= (dma_addr_t)~3;
        rxbuffer->len = len;
        return 0;
 }
@@ -425,9 +427,10 @@ static int tse_rx(struct altera_tse_private *priv, int limit)
                priv->dev->stats.rx_bytes += pktlength;
 
                entry = next_entry;
+
+               tse_rx_refill(priv);
        }
 
-       tse_rx_refill(priv);
        return count;
 }
 
@@ -520,7 +523,6 @@ static irqreturn_t altera_isr(int irq, void *dev_id)
        struct altera_tse_private *priv;
        unsigned long int flags;
 
-
        if (unlikely(!dev)) {
                pr_err("%s: invalid dev pointer\n", __func__);
                return IRQ_NONE;
@@ -562,7 +564,6 @@ static int tse_start_xmit(struct sk_buff *skb, struct net_device *dev)
        unsigned int nopaged_len = skb_headlen(skb);
        enum netdev_tx ret = NETDEV_TX_OK;
        dma_addr_t dma_addr;
-       int txcomplete = 0;
 
        spin_lock_bh(&priv->tx_lock);
 
@@ -598,7 +599,7 @@ static int tse_start_xmit(struct sk_buff *skb, struct net_device *dev)
        dma_sync_single_for_device(priv->device, buffer->dma_addr,
                                   buffer->len, DMA_TO_DEVICE);
 
-       txcomplete = priv->dmaops->tx_buffer(priv, buffer);
+       priv->dmaops->tx_buffer(priv, buffer);
 
        skb_tx_timestamp(skb);
 
@@ -697,7 +698,6 @@ static struct phy_device *connect_local_phy(struct net_device *dev)
        struct altera_tse_private *priv = netdev_priv(dev);
        struct phy_device *phydev = NULL;
        char phy_id_fmt[MII_BUS_ID_SIZE + 3];
-       int ret;
 
        if (priv->phy_addr != POLL_PHY) {
                snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT,
@@ -711,6 +711,7 @@ static struct phy_device *connect_local_phy(struct net_device *dev)
                        netdev_err(dev, "Could not attach to PHY\n");
 
        } else {
+               int ret;
                phydev = phy_find_first(priv->mdio);
                if (phydev == NULL) {
                        netdev_err(dev, "No PHY found\n");
@@ -790,7 +791,6 @@ static int init_phy(struct net_device *dev)
 
 static void tse_update_mac_addr(struct altera_tse_private *priv, u8 *addr)
 {
-       struct altera_tse_mac *mac = priv->mac_dev;
        u32 msb;
        u32 lsb;
 
@@ -798,8 +798,8 @@ static void tse_update_mac_addr(struct altera_tse_private *priv, u8 *addr)
        lsb = ((addr[5] << 8) | addr[4]) & 0xffff;
 
        /* Set primary MAC address */
-       iowrite32(msb, &mac->mac_addr_0);
-       iowrite32(lsb, &mac->mac_addr_1);
+       csrwr32(msb, priv->mac_dev, tse_csroffs(mac_addr_0));
+       csrwr32(lsb, priv->mac_dev, tse_csroffs(mac_addr_1));
 }
 
 /* MAC software reset.
@@ -810,26 +810,26 @@ static void tse_update_mac_addr(struct altera_tse_private *priv, u8 *addr)
  */
 static int reset_mac(struct altera_tse_private *priv)
 {
-       void __iomem *cmd_cfg_reg = &priv->mac_dev->command_config;
        int counter;
        u32 dat;
 
-       dat = ioread32(cmd_cfg_reg);
+       dat = csrrd32(priv->mac_dev, tse_csroffs(command_config));
        dat &= ~(MAC_CMDCFG_TX_ENA | MAC_CMDCFG_RX_ENA);
        dat |= MAC_CMDCFG_SW_RESET | MAC_CMDCFG_CNT_RESET;
-       iowrite32(dat, cmd_cfg_reg);
+       csrwr32(dat, priv->mac_dev, tse_csroffs(command_config));
 
        counter = 0;
        while (counter++ < ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) {
-               if (tse_bit_is_clear(cmd_cfg_reg, MAC_CMDCFG_SW_RESET))
+               if (tse_bit_is_clear(priv->mac_dev, tse_csroffs(command_config),
+                                    MAC_CMDCFG_SW_RESET))
                        break;
                udelay(1);
        }
 
        if (counter >= ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) {
-               dat = ioread32(cmd_cfg_reg);
+               dat = csrrd32(priv->mac_dev, tse_csroffs(command_config));
                dat &= ~MAC_CMDCFG_SW_RESET;
-               iowrite32(dat, cmd_cfg_reg);
+               csrwr32(dat, priv->mac_dev, tse_csroffs(command_config));
                return -1;
        }
        return 0;
@@ -839,42 +839,58 @@ static int reset_mac(struct altera_tse_private *priv)
 */
 static int init_mac(struct altera_tse_private *priv)
 {
-       struct altera_tse_mac *mac = priv->mac_dev;
        unsigned int cmd = 0;
        u32 frm_length;
 
        /* Setup Rx FIFO */
-       iowrite32(priv->rx_fifo_depth - ALTERA_TSE_RX_SECTION_EMPTY,
-                 &mac->rx_section_empty);
-       iowrite32(ALTERA_TSE_RX_SECTION_FULL, &mac->rx_section_full);
-       iowrite32(ALTERA_TSE_RX_ALMOST_EMPTY, &mac->rx_almost_empty);
-       iowrite32(ALTERA_TSE_RX_ALMOST_FULL, &mac->rx_almost_full);
+       csrwr32(priv->rx_fifo_depth - ALTERA_TSE_RX_SECTION_EMPTY,
+               priv->mac_dev, tse_csroffs(rx_section_empty));
+
+       csrwr32(ALTERA_TSE_RX_SECTION_FULL, priv->mac_dev,
+               tse_csroffs(rx_section_full));
+
+       csrwr32(ALTERA_TSE_RX_ALMOST_EMPTY, priv->mac_dev,
+               tse_csroffs(rx_almost_empty));
+
+       csrwr32(ALTERA_TSE_RX_ALMOST_FULL, priv->mac_dev,
+               tse_csroffs(rx_almost_full));
 
        /* Setup Tx FIFO */
-       iowrite32(priv->tx_fifo_depth - ALTERA_TSE_TX_SECTION_EMPTY,
-                 &mac->tx_section_empty);
-       iowrite32(ALTERA_TSE_TX_SECTION_FULL, &mac->tx_section_full);
-       iowrite32(ALTERA_TSE_TX_ALMOST_EMPTY, &mac->tx_almost_empty);
-       iowrite32(ALTERA_TSE_TX_ALMOST_FULL, &mac->tx_almost_full);
+       csrwr32(priv->tx_fifo_depth - ALTERA_TSE_TX_SECTION_EMPTY,
+               priv->mac_dev, tse_csroffs(tx_section_empty));
+
+       csrwr32(ALTERA_TSE_TX_SECTION_FULL, priv->mac_dev,
+               tse_csroffs(tx_section_full));
+
+       csrwr32(ALTERA_TSE_TX_ALMOST_EMPTY, priv->mac_dev,
+               tse_csroffs(tx_almost_empty));
+
+       csrwr32(ALTERA_TSE_TX_ALMOST_FULL, priv->mac_dev,
+               tse_csroffs(tx_almost_full));
 
        /* MAC Address Configuration */
        tse_update_mac_addr(priv, priv->dev->dev_addr);
 
        /* MAC Function Configuration */
        frm_length = ETH_HLEN + priv->dev->mtu + ETH_FCS_LEN;
-       iowrite32(frm_length, &mac->frm_length);
-       iowrite32(ALTERA_TSE_TX_IPG_LENGTH, &mac->tx_ipg_length);
+       csrwr32(frm_length, priv->mac_dev, tse_csroffs(frm_length));
+
+       csrwr32(ALTERA_TSE_TX_IPG_LENGTH, priv->mac_dev,
+               tse_csroffs(tx_ipg_length));
 
        /* Disable RX/TX shift 16 for alignment of all received frames on 16-bit
         * start address
         */
-       tse_clear_bit(&mac->rx_cmd_stat, ALTERA_TSE_RX_CMD_STAT_RX_SHIFT16);
-       tse_clear_bit(&mac->tx_cmd_stat, ALTERA_TSE_TX_CMD_STAT_TX_SHIFT16 |
-                                        ALTERA_TSE_TX_CMD_STAT_OMIT_CRC);
+       tse_set_bit(priv->mac_dev, tse_csroffs(rx_cmd_stat),
+                   ALTERA_TSE_RX_CMD_STAT_RX_SHIFT16);
+
+       tse_clear_bit(priv->mac_dev, tse_csroffs(tx_cmd_stat),
+                     ALTERA_TSE_TX_CMD_STAT_TX_SHIFT16 |
+                     ALTERA_TSE_TX_CMD_STAT_OMIT_CRC);
 
        /* Set the MAC options */
-       cmd = ioread32(&mac->command_config);
-       cmd |= MAC_CMDCFG_PAD_EN;       /* Padding Removal on Receive */
+       cmd = csrrd32(priv->mac_dev, tse_csroffs(command_config));
+       cmd &= ~MAC_CMDCFG_PAD_EN;      /* No padding Removal on Receive */
        cmd &= ~MAC_CMDCFG_CRC_FWD;     /* CRC Removal */
        cmd |= MAC_CMDCFG_RX_ERR_DISC;  /* Automatically discard frames
                                         * with CRC errors
@@ -882,7 +898,16 @@ static int init_mac(struct altera_tse_private *priv)
        cmd |= MAC_CMDCFG_CNTL_FRM_ENA;
        cmd &= ~MAC_CMDCFG_TX_ENA;
        cmd &= ~MAC_CMDCFG_RX_ENA;
-       iowrite32(cmd, &mac->command_config);
+
+       /* Default speed and duplex setting, full/100 */
+       cmd &= ~MAC_CMDCFG_HD_ENA;
+       cmd &= ~MAC_CMDCFG_ETH_SPEED;
+       cmd &= ~MAC_CMDCFG_ENA_10;
+
+       csrwr32(cmd, priv->mac_dev, tse_csroffs(command_config));
+
+       csrwr32(ALTERA_TSE_PAUSE_QUANTA, priv->mac_dev,
+               tse_csroffs(pause_quanta));
 
        if (netif_msg_hw(priv))
                dev_dbg(priv->device,
@@ -895,15 +920,14 @@ static int init_mac(struct altera_tse_private *priv)
  */
 static void tse_set_mac(struct altera_tse_private *priv, bool enable)
 {
-       struct altera_tse_mac *mac = priv->mac_dev;
-       u32 value = ioread32(&mac->command_config);
+       u32 value = csrrd32(priv->mac_dev, tse_csroffs(command_config));
 
        if (enable)
                value |= MAC_CMDCFG_TX_ENA | MAC_CMDCFG_RX_ENA;
        else
                value &= ~(MAC_CMDCFG_TX_ENA | MAC_CMDCFG_RX_ENA);
 
-       iowrite32(value, &mac->command_config);
+       csrwr32(value, priv->mac_dev, tse_csroffs(command_config));
 }
 
 /* Change the MTU
@@ -933,13 +957,12 @@ static int tse_change_mtu(struct net_device *dev, int new_mtu)
 static void altera_tse_set_mcfilter(struct net_device *dev)
 {
        struct altera_tse_private *priv = netdev_priv(dev);
-       struct altera_tse_mac *mac = priv->mac_dev;
        int i;
        struct netdev_hw_addr *ha;
 
        /* clear the hash filter */
        for (i = 0; i < 64; i++)
-               iowrite32(0, &(mac->hash_table[i]));
+               csrwr32(0, priv->mac_dev, tse_csroffs(hash_table) + i * 4);
 
        netdev_for_each_mc_addr(ha, dev) {
                unsigned int hash = 0;
@@ -955,7 +978,7 @@ static void altera_tse_set_mcfilter(struct net_device *dev)
 
                        hash = (hash << 1) | xor_bit;
                }
-               iowrite32(1, &(mac->hash_table[hash]));
+               csrwr32(1, priv->mac_dev, tse_csroffs(hash_table) + hash * 4);
        }
 }
 
@@ -963,12 +986,11 @@ static void altera_tse_set_mcfilter(struct net_device *dev)
 static void altera_tse_set_mcfilterall(struct net_device *dev)
 {
        struct altera_tse_private *priv = netdev_priv(dev);
-       struct altera_tse_mac *mac = priv->mac_dev;
        int i;
 
        /* set the hash filter */
        for (i = 0; i < 64; i++)
-               iowrite32(1, &(mac->hash_table[i]));
+               csrwr32(1, priv->mac_dev, tse_csroffs(hash_table) + i * 4);
 }
 
 /* Set or clear the multicast filter for this adaptor
@@ -976,12 +998,12 @@ static void altera_tse_set_mcfilterall(struct net_device *dev)
 static void tse_set_rx_mode_hashfilter(struct net_device *dev)
 {
        struct altera_tse_private *priv = netdev_priv(dev);
-       struct altera_tse_mac *mac = priv->mac_dev;
 
        spin_lock(&priv->mac_cfg_lock);
 
        if (dev->flags & IFF_PROMISC)
-               tse_set_bit(&mac->command_config, MAC_CMDCFG_PROMIS_EN);
+               tse_set_bit(priv->mac_dev, tse_csroffs(command_config),
+                           MAC_CMDCFG_PROMIS_EN);
 
        if (dev->flags & IFF_ALLMULTI)
                altera_tse_set_mcfilterall(dev);
@@ -996,15 +1018,16 @@ static void tse_set_rx_mode_hashfilter(struct net_device *dev)
 static void tse_set_rx_mode(struct net_device *dev)
 {
        struct altera_tse_private *priv = netdev_priv(dev);
-       struct altera_tse_mac *mac = priv->mac_dev;
 
        spin_lock(&priv->mac_cfg_lock);
 
        if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||
            !netdev_mc_empty(dev) || !netdev_uc_empty(dev))
-               tse_set_bit(&mac->command_config, MAC_CMDCFG_PROMIS_EN);
+               tse_set_bit(priv->mac_dev, tse_csroffs(command_config),
+                           MAC_CMDCFG_PROMIS_EN);
        else
-               tse_clear_bit(&mac->command_config, MAC_CMDCFG_PROMIS_EN);
+               tse_clear_bit(priv->mac_dev, tse_csroffs(command_config),
+                             MAC_CMDCFG_PROMIS_EN);
 
        spin_unlock(&priv->mac_cfg_lock);
 }
@@ -1085,17 +1108,19 @@ static int tse_open(struct net_device *dev)
 
        spin_unlock_irqrestore(&priv->rxdma_irq_lock, flags);
 
-       /* Start MAC Rx/Tx */
-       spin_lock(&priv->mac_cfg_lock);
-       tse_set_mac(priv, true);
-       spin_unlock(&priv->mac_cfg_lock);
-
        if (priv->phydev)
                phy_start(priv->phydev);
 
        napi_enable(&priv->napi);
        netif_start_queue(dev);
 
+       priv->dmaops->start_rxdma(priv);
+
+       /* Start MAC Rx/Tx */
+       spin_lock(&priv->mac_cfg_lock);
+       tse_set_mac(priv, true);
+       spin_unlock(&priv->mac_cfg_lock);
+
        return 0;
 
 tx_request_irq_error:
@@ -1167,7 +1192,6 @@ static struct net_device_ops altera_tse_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-
 static int request_and_map(struct platform_device *pdev, const char *name,
                           struct resource **res, void __iomem **ptr)
 {
@@ -1235,7 +1259,7 @@ static int altera_tse_probe(struct platform_device *pdev)
                /* Get the mapped address to the SGDMA descriptor memory */
                ret = request_and_map(pdev, "s1", &dma_res, &descmap);
                if (ret)
-                       goto out_free;
+                       goto err_free_netdev;
 
                /* Start of that memory is for transmit descriptors */
                priv->tx_dma_desc = descmap;
@@ -1254,24 +1278,24 @@ static int altera_tse_probe(struct platform_device *pdev)
                if (upper_32_bits(priv->rxdescmem_busaddr)) {
                        dev_dbg(priv->device,
                                "SGDMA bus addresses greater than 32-bits\n");
-                       goto out_free;
+                       goto err_free_netdev;
                }
                if (upper_32_bits(priv->txdescmem_busaddr)) {
                        dev_dbg(priv->device,
                                "SGDMA bus addresses greater than 32-bits\n");
-                       goto out_free;
+                       goto err_free_netdev;
                }
        } else if (priv->dmaops &&
                   priv->dmaops->altera_dtype == ALTERA_DTYPE_MSGDMA) {
                ret = request_and_map(pdev, "rx_resp", &dma_res,
                                      &priv->rx_dma_resp);
                if (ret)
-                       goto out_free;
+                       goto err_free_netdev;
 
                ret = request_and_map(pdev, "tx_desc", &dma_res,
                                      &priv->tx_dma_desc);
                if (ret)
-                       goto out_free;
+                       goto err_free_netdev;
 
                priv->txdescmem = resource_size(dma_res);
                priv->txdescmem_busaddr = dma_res->start;
@@ -1279,13 +1303,13 @@ static int altera_tse_probe(struct platform_device *pdev)
                ret = request_and_map(pdev, "rx_desc", &dma_res,
                                      &priv->rx_dma_desc);
                if (ret)
-                       goto out_free;
+                       goto err_free_netdev;
 
                priv->rxdescmem = resource_size(dma_res);
                priv->rxdescmem_busaddr = dma_res->start;
 
        } else {
-               goto out_free;
+               goto err_free_netdev;
        }
 
        if (!dma_set_mask(priv->device, DMA_BIT_MASK(priv->dmaops->dmamask)))
@@ -1294,26 +1318,26 @@ static int altera_tse_probe(struct platform_device *pdev)
        else if (!dma_set_mask(priv->device, DMA_BIT_MASK(32)))
                dma_set_coherent_mask(priv->device, DMA_BIT_MASK(32));
        else
-               goto out_free;
+               goto err_free_netdev;
 
        /* MAC address space */
        ret = request_and_map(pdev, "control_port", &control_port,
                              (void __iomem **)&priv->mac_dev);
        if (ret)
-               goto out_free;
+               goto err_free_netdev;
 
        /* xSGDMA Rx Dispatcher address space */
        ret = request_and_map(pdev, "rx_csr", &dma_res,
                              &priv->rx_dma_csr);
        if (ret)
-               goto out_free;
+               goto err_free_netdev;
 
 
        /* xSGDMA Tx Dispatcher address space */
        ret = request_and_map(pdev, "tx_csr", &dma_res,
                              &priv->tx_dma_csr);
        if (ret)
-               goto out_free;
+               goto err_free_netdev;
 
 
        /* Rx IRQ */
@@ -1321,7 +1345,7 @@ static int altera_tse_probe(struct platform_device *pdev)
        if (priv->rx_irq == -ENXIO) {
                dev_err(&pdev->dev, "cannot obtain Rx IRQ\n");
                ret = -ENXIO;
-               goto out_free;
+               goto err_free_netdev;
        }
 
        /* Tx IRQ */
@@ -1329,7 +1353,7 @@ static int altera_tse_probe(struct platform_device *pdev)
        if (priv->tx_irq == -ENXIO) {
                dev_err(&pdev->dev, "cannot obtain Tx IRQ\n");
                ret = -ENXIO;
-               goto out_free;
+               goto err_free_netdev;
        }
 
        /* get FIFO depths from device tree */
@@ -1337,14 +1361,14 @@ static int altera_tse_probe(struct platform_device *pdev)
                                 &priv->rx_fifo_depth)) {
                dev_err(&pdev->dev, "cannot obtain rx-fifo-depth\n");
                ret = -ENXIO;
-               goto out_free;
+               goto err_free_netdev;
        }
 
        if (of_property_read_u32(pdev->dev.of_node, "tx-fifo-depth",
                                 &priv->rx_fifo_depth)) {
                dev_err(&pdev->dev, "cannot obtain tx-fifo-depth\n");
                ret = -ENXIO;
-               goto out_free;
+               goto err_free_netdev;
        }
 
        /* get hash filter settings for this instance */
@@ -1352,6 +1376,11 @@ static int altera_tse_probe(struct platform_device *pdev)
                of_property_read_bool(pdev->dev.of_node,
                                      "altr,has-hash-multicast-filter");
 
+       /* Set hash filter to not set for now until the
+        * multicast filter receive issue is debugged
+        */
+       priv->hash_filter = 0;
+
        /* get supplemental address settings for this instance */
        priv->added_unicast =
                of_property_read_bool(pdev->dev.of_node,
@@ -1393,7 +1422,7 @@ static int altera_tse_probe(struct platform_device *pdev)
              ((priv->phy_addr >= 0) && (priv->phy_addr < PHY_MAX_ADDR)))) {
                dev_err(&pdev->dev, "invalid phy-addr specified %d\n",
                        priv->phy_addr);
-               goto out_free;
+               goto err_free_netdev;
        }
 
        /* Create/attach to MDIO bus */
@@ -1401,7 +1430,7 @@ static int altera_tse_probe(struct platform_device *pdev)
                                     atomic_add_return(1, &instance_count));
 
        if (ret)
-               goto out_free;
+               goto err_free_netdev;
 
        /* initialize netdev */
        ether_setup(ndev);
@@ -1438,7 +1467,7 @@ static int altera_tse_probe(struct platform_device *pdev)
        ret = register_netdev(ndev);
        if (ret) {
                dev_err(&pdev->dev, "failed to register TSE net device\n");
-               goto out_free_mdio;
+               goto err_register_netdev;
        }
 
        platform_set_drvdata(pdev, ndev);
@@ -1455,13 +1484,16 @@ static int altera_tse_probe(struct platform_device *pdev)
        ret = init_phy(ndev);
        if (ret != 0) {
                netdev_err(ndev, "Cannot attach to PHY (error: %d)\n", ret);
-               goto out_free_mdio;
+               goto err_init_phy;
        }
        return 0;
 
-out_free_mdio:
+err_init_phy:
+       unregister_netdev(ndev);
+err_register_netdev:
+       netif_napi_del(&priv->napi);
        altera_tse_mdio_destroy(ndev);
-out_free:
+err_free_netdev:
        free_netdev(ndev);
        return ret;
 }
@@ -1480,7 +1512,7 @@ static int altera_tse_remove(struct platform_device *pdev)
        return 0;
 }
 
-struct altera_dmaops altera_dtype_sgdma = {
+static const struct altera_dmaops altera_dtype_sgdma = {
        .altera_dtype = ALTERA_DTYPE_SGDMA,
        .dmamask = 32,
        .reset_dma = sgdma_reset,
@@ -1496,9 +1528,10 @@ struct altera_dmaops altera_dtype_sgdma = {
        .get_rx_status = sgdma_rx_status,
        .init_dma = sgdma_initialize,
        .uninit_dma = sgdma_uninitialize,
+       .start_rxdma = sgdma_start_rxdma,
 };
 
-struct altera_dmaops altera_dtype_msgdma = {
+static const struct altera_dmaops altera_dtype_msgdma = {
        .altera_dtype = ALTERA_DTYPE_MSGDMA,
        .dmamask = 64,
        .reset_dma = msgdma_reset,
@@ -1514,6 +1547,7 @@ struct altera_dmaops altera_dtype_msgdma = {
        .get_rx_status = msgdma_rx_status,
        .init_dma = msgdma_initialize,
        .uninit_dma = msgdma_uninitialize,
+       .start_rxdma = msgdma_start_rxdma,
 };
 
 static struct of_device_id altera_tse_ids[] = {
index 70fa13f486b2fc4ef1d6fc45bb82977d13ea1930..d7eeb1713ad2b85721a533fbcc469d22db5740ea 100644 (file)
 #include "altera_tse.h"
 #include "altera_utils.h"
 
-void tse_set_bit(void __iomem *ioaddr, u32 bit_mask)
+void tse_set_bit(void __iomem *ioaddr, size_t offs, u32 bit_mask)
 {
-       u32 value = ioread32(ioaddr);
+       u32 value = csrrd32(ioaddr, offs);
        value |= bit_mask;
-       iowrite32(value, ioaddr);
+       csrwr32(value, ioaddr, offs);
 }
 
-void tse_clear_bit(void __iomem *ioaddr, u32 bit_mask)
+void tse_clear_bit(void __iomem *ioaddr, size_t offs, u32 bit_mask)
 {
-       u32 value = ioread32(ioaddr);
+       u32 value = csrrd32(ioaddr, offs);
        value &= ~bit_mask;
-       iowrite32(value, ioaddr);
+       csrwr32(value, ioaddr, offs);
 }
 
-int tse_bit_is_set(void __iomem *ioaddr, u32 bit_mask)
+int tse_bit_is_set(void __iomem *ioaddr, size_t offs, u32 bit_mask)
 {
-       u32 value = ioread32(ioaddr);
+       u32 value = csrrd32(ioaddr, offs);
        return (value & bit_mask) ? 1 : 0;
 }
 
-int tse_bit_is_clear(void __iomem *ioaddr, u32 bit_mask)
+int tse_bit_is_clear(void __iomem *ioaddr, size_t offs, u32 bit_mask)
 {
-       u32 value = ioread32(ioaddr);
+       u32 value = csrrd32(ioaddr, offs);
        return (value & bit_mask) ? 0 : 1;
 }
index ce1db36d35832a974f9f958f0b57c298343c0967..baf100ccf5872c7c18ac365ddfe314308b78c9b5 100644 (file)
@@ -19,9 +19,9 @@
 #ifndef __ALTERA_UTILS_H__
 #define __ALTERA_UTILS_H__
 
-void tse_set_bit(void __iomem *ioaddr, u32 bit_mask);
-void tse_clear_bit(void __iomem *ioaddr, u32 bit_mask);
-int tse_bit_is_set(void __iomem *ioaddr, u32 bit_mask);
-int tse_bit_is_clear(void __iomem *ioaddr, u32 bit_mask);
+void tse_set_bit(void __iomem *ioaddr, size_t offs, u32 bit_mask);
+void tse_clear_bit(void __iomem *ioaddr, size_t offs, u32 bit_mask);
+int tse_bit_is_set(void __iomem *ioaddr, size_t offs, u32 bit_mask);
+int tse_bit_is_clear(void __iomem *ioaddr, size_t offs, u32 bit_mask);
 
 #endif /* __ALTERA_UTILS_H__*/
index 928fac6dd10a90dca66244dba99194c9c9e2924d..53f85bf715268db94d864695321e3890454719ce 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/netdevice.h>
 #include <linux/phy.h>
+#include <linux/clk.h>
 
 /* STATUS and ENABLE Register bit masks */
 #define TXINT_MASK     (1<<0)  /* Transmit interrupt */
@@ -131,6 +132,7 @@ struct arc_emac_priv {
        struct mii_bus *bus;
 
        void __iomem *regs;
+       struct clk *clk;
 
        struct napi_struct napi;
        struct net_device_stats stats;
index eeecc29cf5b7d2695739d819fe900e798bf38996..d647a7d115acb2e7d40f72ee5010cd1e6ea79982 100644 (file)
@@ -574,6 +574,18 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
        return NETDEV_TX_OK;
 }
 
+static void arc_emac_set_address_internal(struct net_device *ndev)
+{
+       struct arc_emac_priv *priv = netdev_priv(ndev);
+       unsigned int addr_low, addr_hi;
+
+       addr_low = le32_to_cpu(*(__le32 *) &ndev->dev_addr[0]);
+       addr_hi = le16_to_cpu(*(__le16 *) &ndev->dev_addr[4]);
+
+       arc_reg_set(priv, R_ADDRL, addr_low);
+       arc_reg_set(priv, R_ADDRH, addr_hi);
+}
+
 /**
  * arc_emac_set_address - Set the MAC address for this device.
  * @ndev:      Pointer to net_device structure.
@@ -587,9 +599,7 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev)
  */
 static int arc_emac_set_address(struct net_device *ndev, void *p)
 {
-       struct arc_emac_priv *priv = netdev_priv(ndev);
        struct sockaddr *addr = p;
-       unsigned int addr_low, addr_hi;
 
        if (netif_running(ndev))
                return -EBUSY;
@@ -599,11 +609,7 @@ static int arc_emac_set_address(struct net_device *ndev, void *p)
 
        memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
 
-       addr_low = le32_to_cpu(*(__le32 *) &ndev->dev_addr[0]);
-       addr_hi = le16_to_cpu(*(__le16 *) &ndev->dev_addr[4]);
-
-       arc_reg_set(priv, R_ADDRL, addr_low);
-       arc_reg_set(priv, R_ADDRH, addr_hi);
+       arc_emac_set_address_internal(ndev);
 
        return 0;
 }
@@ -643,13 +649,6 @@ static int arc_emac_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       /* Get CPU clock frequency from device tree */
-       if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
-                                &clock_frequency)) {
-               dev_err(&pdev->dev, "failed to retrieve <clock-frequency> from device tree\n");
-               return -EINVAL;
-       }
-
        /* Get IRQ from device tree */
        irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
        if (!irq) {
@@ -677,17 +676,36 @@ static int arc_emac_probe(struct platform_device *pdev)
        priv->regs = devm_ioremap_resource(&pdev->dev, &res_regs);
        if (IS_ERR(priv->regs)) {
                err = PTR_ERR(priv->regs);
-               goto out;
+               goto out_netdev;
        }
        dev_dbg(&pdev->dev, "Registers base address is 0x%p\n", priv->regs);
 
+       priv->clk = of_clk_get(pdev->dev.of_node, 0);
+       if (IS_ERR(priv->clk)) {
+               /* Get CPU clock frequency from device tree */
+               if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+                                       &clock_frequency)) {
+                       dev_err(&pdev->dev, "failed to retrieve <clock-frequency> from device tree\n");
+                       err = -EINVAL;
+                       goto out_netdev;
+               }
+       } else {
+               err = clk_prepare_enable(priv->clk);
+               if (err) {
+                       dev_err(&pdev->dev, "failed to enable clock\n");
+                       goto out_clkget;
+               }
+
+               clock_frequency = clk_get_rate(priv->clk);
+       }
+
        id = arc_reg_get(priv, R_ID);
 
        /* Check for EMAC revision 5 or 7, magic number */
        if (!(id == 0x0005fd02 || id == 0x0007fd02)) {
                dev_err(&pdev->dev, "ARC EMAC not detected, id=0x%x\n", id);
                err = -ENODEV;
-               goto out;
+               goto out_clken;
        }
        dev_info(&pdev->dev, "ARC EMAC detected with id: 0x%x\n", id);
 
@@ -702,7 +720,7 @@ static int arc_emac_probe(struct platform_device *pdev)
                               ndev->name, ndev);
        if (err) {
                dev_err(&pdev->dev, "could not allocate IRQ\n");
-               goto out;
+               goto out_clken;
        }
 
        /* Get MAC address from device tree */
@@ -713,6 +731,7 @@ static int arc_emac_probe(struct platform_device *pdev)
        else
                eth_hw_addr_random(ndev);
 
+       arc_emac_set_address_internal(ndev);
        dev_info(&pdev->dev, "MAC address is now %pM\n", ndev->dev_addr);
 
        /* Do 1 allocation instead of 2 separate ones for Rx and Tx BD rings */
@@ -722,7 +741,7 @@ static int arc_emac_probe(struct platform_device *pdev)
        if (!priv->rxbd) {
                dev_err(&pdev->dev, "failed to allocate data buffers\n");
                err = -ENOMEM;
-               goto out;
+               goto out_clken;
        }
 
        priv->txbd = priv->rxbd + RX_BD_NUM;
@@ -734,7 +753,7 @@ static int arc_emac_probe(struct platform_device *pdev)
        err = arc_mdio_probe(pdev, priv);
        if (err) {
                dev_err(&pdev->dev, "failed to probe MII bus\n");
-               goto out;
+               goto out_clken;
        }
 
        priv->phy_dev = of_phy_connect(ndev, phy_node, arc_emac_adjust_link, 0,
@@ -742,7 +761,7 @@ static int arc_emac_probe(struct platform_device *pdev)
        if (!priv->phy_dev) {
                dev_err(&pdev->dev, "of_phy_connect() failed\n");
                err = -ENODEV;
-               goto out;
+               goto out_mdio;
        }
 
        dev_info(&pdev->dev, "connected to %s phy with id 0x%x\n",
@@ -752,14 +771,25 @@ static int arc_emac_probe(struct platform_device *pdev)
 
        err = register_netdev(ndev);
        if (err) {
-               netif_napi_del(&priv->napi);
                dev_err(&pdev->dev, "failed to register network device\n");
-               goto out;
+               goto out_netif_api;
        }
 
        return 0;
 
-out:
+out_netif_api:
+       netif_napi_del(&priv->napi);
+       phy_disconnect(priv->phy_dev);
+       priv->phy_dev = NULL;
+out_mdio:
+       arc_mdio_remove(priv);
+out_clken:
+       if (!IS_ERR(priv->clk))
+               clk_disable_unprepare(priv->clk);
+out_clkget:
+       if (!IS_ERR(priv->clk))
+               clk_put(priv->clk);
+out_netdev:
        free_netdev(ndev);
        return err;
 }
@@ -774,6 +804,12 @@ static int arc_emac_remove(struct platform_device *pdev)
        arc_mdio_remove(priv);
        unregister_netdev(ndev);
        netif_napi_del(&priv->napi);
+
+       if (!IS_ERR(priv->clk)) {
+               clk_disable_unprepare(priv->clk);
+               clk_put(priv->clk);
+       }
+
        free_netdev(ndev);
 
        return 0;
index a78edaccceee92d8f2439ac40f3b3ba887ec0000..3b0d43154e677bfe8fd1f66aac7d3c0a6afbcfd5 100644 (file)
@@ -10051,8 +10051,8 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp,
 #define BCM_5710_UNDI_FW_MF_MAJOR      (0x07)
 #define BCM_5710_UNDI_FW_MF_MINOR      (0x08)
 #define BCM_5710_UNDI_FW_MF_VERS       (0x05)
-#define BNX2X_PREV_UNDI_MF_PORT(p)     (0x1a150c + ((p) << 4))
-#define BNX2X_PREV_UNDI_MF_FUNC(f)     (0x1a184c + ((f) << 4))
+#define BNX2X_PREV_UNDI_MF_PORT(p) (BAR_TSTRORM_INTMEM + 0x150c + ((p) << 4))
+#define BNX2X_PREV_UNDI_MF_FUNC(f) (BAR_TSTRORM_INTMEM + 0x184c + ((f) << 4))
 static bool bnx2x_prev_unload_undi_fw_supports_mf(struct bnx2x *bp)
 {
        u8 major, minor, version;
@@ -10352,6 +10352,7 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
        /* Reset should be performed after BRB is emptied */
        if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_BRB1) {
                u32 timer_count = 1000;
+               bool need_write = true;
 
                /* Close the MAC Rx to prevent BRB from filling up */
                bnx2x_prev_unload_close_mac(bp, &mac_vals);
@@ -10398,7 +10399,10 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp)
                         * cleaning methods - might be redundant but harmless.
                         */
                        if (bnx2x_prev_unload_undi_fw_supports_mf(bp)) {
-                               bnx2x_prev_unload_undi_mf(bp);
+                               if (need_write) {
+                                       bnx2x_prev_unload_undi_mf(bp);
+                                       need_write = false;
+                               }
                        } else if (prev_undi) {
                                /* If UNDI resides in memory,
                                 * manually increment it
@@ -13233,6 +13237,8 @@ static void __bnx2x_remove(struct pci_dev *pdev,
                                iounmap(bp->doorbells);
 
                        bnx2x_release_firmware(bp);
+               } else {
+                       bnx2x_vf_pci_dealloc(bp);
                }
                bnx2x_free_mem_bp(bp);
 
index 5c523b32db70126720dbf0b2914dcbb1a3391a2b..b8078d50261bf0944f456acc466c73c138b03306 100644 (file)
@@ -427,7 +427,9 @@ static int bnx2x_vf_mac_vlan_config(struct bnx2x *bp,
        if (filter->add && filter->type == BNX2X_VF_FILTER_VLAN &&
            (atomic_read(&bnx2x_vfq(vf, qid, vlan_count)) >=
             vf_vlan_rules_cnt(vf))) {
-               BNX2X_ERR("No credits for vlan\n");
+               BNX2X_ERR("No credits for vlan [%d >= %d]\n",
+                         atomic_read(&bnx2x_vfq(vf, qid, vlan_count)),
+                         vf_vlan_rules_cnt(vf));
                return -ENOMEM;
        }
 
@@ -610,6 +612,7 @@ int bnx2x_vf_mcast(struct bnx2x *bp, struct bnx2x_virtf *vf,
                }
 
                /* add new mcasts */
+               mcast.mcast_list_len = mc_num;
                rc = bnx2x_config_mcast(bp, &mcast, BNX2X_MCAST_CMD_ADD);
                if (rc)
                        BNX2X_ERR("Faled to add multicasts\n");
@@ -837,6 +840,29 @@ int bnx2x_vf_flr_clnup_epilog(struct bnx2x *bp, u8 abs_vfid)
        return 0;
 }
 
+static void bnx2x_iov_re_set_vlan_filters(struct bnx2x *bp,
+                                         struct bnx2x_virtf *vf,
+                                         int new)
+{
+       int num = vf_vlan_rules_cnt(vf);
+       int diff = new - num;
+       bool rc = true;
+
+       DP(BNX2X_MSG_IOV, "vf[%d] - %d vlan filter credits [previously %d]\n",
+          vf->abs_vfid, new, num);
+
+       if (diff > 0)
+               rc = bp->vlans_pool.get(&bp->vlans_pool, diff);
+       else if (diff < 0)
+               rc = bp->vlans_pool.put(&bp->vlans_pool, -diff);
+
+       if (rc)
+               vf_vlan_rules_cnt(vf) = new;
+       else
+               DP(BNX2X_MSG_IOV, "vf[%d] - Failed to configure vlan filter credits change\n",
+                  vf->abs_vfid);
+}
+
 /* must be called after the number of PF queues and the number of VFs are
  * both known
  */
@@ -854,9 +880,11 @@ bnx2x_iov_static_resc(struct bnx2x *bp, struct bnx2x_virtf *vf)
        resc->num_mac_filters = 1;
 
        /* divvy up vlan rules */
+       bnx2x_iov_re_set_vlan_filters(bp, vf, 0);
        vlan_count = bp->vlans_pool.check(&bp->vlans_pool);
        vlan_count = 1 << ilog2(vlan_count);
-       resc->num_vlan_filters = vlan_count / BNX2X_NR_VIRTFN(bp);
+       bnx2x_iov_re_set_vlan_filters(bp, vf,
+                                     vlan_count / BNX2X_NR_VIRTFN(bp));
 
        /* no real limitation */
        resc->num_mc_filters = 0;
@@ -1478,10 +1506,6 @@ int bnx2x_iov_nic_init(struct bnx2x *bp)
                bnx2x_iov_static_resc(bp, vf);
 
                /* queues are initialized during VF-ACQUIRE */
-
-               /* reserve the vf vlan credit */
-               bp->vlans_pool.get(&bp->vlans_pool, vf_vlan_rules_cnt(vf));
-
                vf->filter_state = 0;
                vf->sp_cl_id = bnx2x_fp(bp, 0, cl_id);
 
@@ -1912,11 +1936,12 @@ int bnx2x_vf_chk_avail_resc(struct bnx2x *bp, struct bnx2x_virtf *vf,
        u8 rxq_cnt = vf_rxq_count(vf) ? : bnx2x_vf_max_queue_cnt(bp, vf);
        u8 txq_cnt = vf_txq_count(vf) ? : bnx2x_vf_max_queue_cnt(bp, vf);
 
+       /* Save a vlan filter for the Hypervisor */
        return ((req_resc->num_rxqs <= rxq_cnt) &&
                (req_resc->num_txqs <= txq_cnt) &&
                (req_resc->num_sbs <= vf_sb_count(vf))   &&
                (req_resc->num_mac_filters <= vf_mac_rules_cnt(vf)) &&
-               (req_resc->num_vlan_filters <= vf_vlan_rules_cnt(vf)));
+               (req_resc->num_vlan_filters <= vf_vlan_rules_visible_cnt(vf)));
 }
 
 /* CORE VF API */
@@ -1972,14 +1997,14 @@ int bnx2x_vf_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
        vf_txq_count(vf) = resc->num_txqs ? : bnx2x_vf_max_queue_cnt(bp, vf);
        if (resc->num_mac_filters)
                vf_mac_rules_cnt(vf) = resc->num_mac_filters;
-       if (resc->num_vlan_filters)
-               vf_vlan_rules_cnt(vf) = resc->num_vlan_filters;
+       /* Add an additional vlan filter credit for the hypervisor */
+       bnx2x_iov_re_set_vlan_filters(bp, vf, resc->num_vlan_filters + 1);
 
        DP(BNX2X_MSG_IOV,
           "Fulfilling vf request: sb count %d, tx_count %d, rx_count %d, mac_rules_count %d, vlan_rules_count %d\n",
           vf_sb_count(vf), vf_rxq_count(vf),
           vf_txq_count(vf), vf_mac_rules_cnt(vf),
-          vf_vlan_rules_cnt(vf));
+          vf_vlan_rules_visible_cnt(vf));
 
        /* Initialize the queues */
        if (!vf->vfqs) {
@@ -2670,7 +2695,7 @@ out:
                bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_MAC);
        }
 
-       return 0;
+       return rc;
 }
 
 int bnx2x_set_vf_vlan(struct net_device *dev, int vfidx, u16 vlan, u8 qos)
@@ -2896,6 +2921,14 @@ void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp)
        return bp->regview + PXP_VF_ADDR_DB_START;
 }
 
+void bnx2x_vf_pci_dealloc(struct bnx2x *bp)
+{
+       BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->vf2pf_mbox_mapping,
+                      sizeof(struct bnx2x_vf_mbx_msg));
+       BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->pf2vf_bulletin_mapping,
+                      sizeof(union pf_vf_bulletin));
+}
+
 int bnx2x_vf_pci_alloc(struct bnx2x *bp)
 {
        mutex_init(&bp->vf2pf_mutex);
@@ -2915,10 +2948,7 @@ int bnx2x_vf_pci_alloc(struct bnx2x *bp)
        return 0;
 
 alloc_mem_err:
-       BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->vf2pf_mbox_mapping,
-                      sizeof(struct bnx2x_vf_mbx_msg));
-       BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->pf2vf_bulletin_mapping,
-                      sizeof(union pf_vf_bulletin));
+       bnx2x_vf_pci_dealloc(bp);
        return -ENOMEM;
 }
 
index 8bf764570eef773eafa87ffd0fca26592e4d64ef..6929adba52f97029cf1b0e4fa44b0838bef7046d 100644 (file)
@@ -159,6 +159,8 @@ struct bnx2x_virtf {
 #define vf_mac_rules_cnt(vf)           ((vf)->alloc_resc.num_mac_filters)
 #define vf_vlan_rules_cnt(vf)          ((vf)->alloc_resc.num_vlan_filters)
 #define vf_mc_rules_cnt(vf)            ((vf)->alloc_resc.num_mc_filters)
+       /* Hide a single vlan filter credit for the hypervisor */
+#define vf_vlan_rules_visible_cnt(vf)  (vf_vlan_rules_cnt(vf) - 1)
 
        u8 sb_count;    /* actual number of SBs */
        u8 igu_base_id; /* base igu status block id */
@@ -502,6 +504,7 @@ static inline int bnx2x_vf_ustorm_prods_offset(struct bnx2x *bp,
 enum sample_bulletin_result bnx2x_sample_bulletin(struct bnx2x *bp);
 void bnx2x_timer_sriov(struct bnx2x *bp);
 void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp);
+void bnx2x_vf_pci_dealloc(struct bnx2x *bp);
 int bnx2x_vf_pci_alloc(struct bnx2x *bp);
 int bnx2x_enable_sriov(struct bnx2x *bp);
 void bnx2x_disable_sriov(struct bnx2x *bp);
@@ -568,6 +571,7 @@ static inline void __iomem *bnx2x_vf_doorbells(struct bnx2x *bp)
        return NULL;
 }
 
+static inline void bnx2x_vf_pci_dealloc(struct bnx2 *bp) {return 0; }
 static inline int bnx2x_vf_pci_alloc(struct bnx2x *bp) {return 0; }
 static inline void bnx2x_pf_set_vfs_vlan(struct bnx2x *bp) {}
 static inline int bnx2x_sriov_configure(struct pci_dev *dev, int num_vfs) {return 0; }
index 0622884596b2f478ec4a2789c17fdd0938544995..784c7155b98a1977f2b809efe4ee5a45b23dc44b 100644 (file)
@@ -747,7 +747,7 @@ int bnx2x_vfpf_config_mac(struct bnx2x *bp, u8 *addr, u8 vf_qid, bool set)
 out:
        bnx2x_vfpf_finalize(bp, &req->first_tlv);
 
-       return 0;
+       return rc;
 }
 
 /* request pf to config rss table for vf queues*/
@@ -1163,7 +1163,7 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
                        bnx2x_vf_max_queue_cnt(bp, vf);
                resc->num_sbs = vf_sb_count(vf);
                resc->num_mac_filters = vf_mac_rules_cnt(vf);
-               resc->num_vlan_filters = vf_vlan_rules_cnt(vf);
+               resc->num_vlan_filters = vf_vlan_rules_visible_cnt(vf);
                resc->num_mc_filters = 0;
 
                if (status == PFVF_STATUS_SUCCESS) {
index 7e49c43b7af3501f953cac4796e4769da542c29d..9e089d24466e65fb6c8b01c08f2ece882e23aaaa 100644 (file)
@@ -4,7 +4,7 @@
 
 config NET_CADENCE
        bool "Cadence devices"
-       depends on HAS_IOMEM && (ARM || AVR32 || COMPILE_TEST)
+       depends on HAS_IOMEM && (ARM || AVR32 || MICROBLAZE || COMPILE_TEST)
        default y
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y.
@@ -30,7 +30,7 @@ config ARM_AT91_ETHER
 
 config MACB
        tristate "Cadence MACB/GEM support"
-       depends on HAS_DMA && (PLATFORM_AT32AP || ARCH_AT91 || ARCH_PICOXCELL || ARCH_ZYNQ || COMPILE_TEST)
+       depends on HAS_DMA && (PLATFORM_AT32AP || ARCH_AT91 || ARCH_PICOXCELL || ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST)
        select PHYLIB
        ---help---
          The Cadence MACB ethernet interface is found on many Atmel AT32 and
index ca97005e24b41217849beaf4b9a578fbaf1f2027..e9daa072ebb4f2c03af453255a9c374bde6ff47c 100644 (file)
@@ -599,25 +599,16 @@ static void gem_rx_refill(struct macb *bp)
 {
        unsigned int            entry;
        struct sk_buff          *skb;
-       struct macb_dma_desc    *desc;
        dma_addr_t              paddr;
 
        while (CIRC_SPACE(bp->rx_prepared_head, bp->rx_tail, RX_RING_SIZE) > 0) {
-               u32 addr, ctrl;
-
                entry = macb_rx_ring_wrap(bp->rx_prepared_head);
-               desc = &bp->rx_ring[entry];
 
                /* Make hw descriptor updates visible to CPU */
                rmb();
 
-               addr = desc->addr;
-               ctrl = desc->ctrl;
                bp->rx_prepared_head++;
 
-               if ((addr & MACB_BIT(RX_USED)))
-                       continue;
-
                if (bp->rx_skbuff[entry] == NULL) {
                        /* allocate sk_buff for this free entry in ring */
                        skb = netdev_alloc_skb(bp->dev, bp->rx_buffer_size);
@@ -698,7 +689,6 @@ static int gem_rx(struct macb *bp, int budget)
                if (!(addr & MACB_BIT(RX_USED)))
                        break;
 
-               desc->addr &= ~MACB_BIT(RX_USED);
                bp->rx_tail++;
                count++;
 
@@ -891,16 +881,15 @@ static int macb_poll(struct napi_struct *napi, int budget)
        if (work_done < budget) {
                napi_complete(napi);
 
-               /*
-                * We've done what we can to clean the buffers. Make sure we
-                * get notified when new packets arrive.
-                */
-               macb_writel(bp, IER, MACB_RX_INT_FLAGS);
-
                /* Packets received while interrupts were disabled */
                status = macb_readl(bp, RSR);
-               if (unlikely(status))
+               if (status) {
+                       if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+                               macb_writel(bp, ISR, MACB_BIT(RCOMP));
                        napi_reschedule(napi);
+               } else {
+                       macb_writel(bp, IER, MACB_RX_INT_FLAGS);
+               }
        }
 
        /* TODO: Handle errors */
@@ -951,6 +940,10 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
                if (unlikely(status & (MACB_TX_ERR_FLAGS))) {
                        macb_writel(bp, IDR, MACB_TX_INT_FLAGS);
                        schedule_work(&bp->tx_error_task);
+
+                       if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+                               macb_writel(bp, ISR, MACB_TX_ERR_FLAGS);
+
                        break;
                }
 
@@ -968,6 +961,9 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
                                bp->hw_stats.gem.rx_overruns++;
                        else
                                bp->hw_stats.macb.rx_overruns++;
+
+                       if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+                               macb_writel(bp, ISR, MACB_BIT(ISR_ROVR));
                }
 
                if (status & MACB_BIT(HRESP)) {
@@ -977,6 +973,9 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
                         * (work queue?)
                         */
                        netdev_err(dev, "DMA bus error: HRESP not OK\n");
+
+                       if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+                               macb_writel(bp, ISR, MACB_BIT(HRESP));
                }
 
                status = macb_readl(bp, ISR);
@@ -1113,7 +1112,7 @@ static void gem_free_rx_buffers(struct macb *bp)
 
                desc = &bp->rx_ring[i];
                addr = MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
-               dma_unmap_single(&bp->pdev->dev, addr, skb->len,
+               dma_unmap_single(&bp->pdev->dev, addr, bp->rx_buffer_size,
                                 DMA_FROM_DEVICE);
                dev_kfree_skb_any(skb);
                skb = NULL;
index d40c994a4f6a2c807965e44eaf81f2be0053fb50..570222c3341070445b3b0c224205872f286a3cfd 100644 (file)
@@ -67,13 +67,13 @@ config CHELSIO_T3
          will be called cxgb3.
 
 config CHELSIO_T4
-       tristate "Chelsio Communications T4 Ethernet support"
+       tristate "Chelsio Communications T4/T5 Ethernet support"
        depends on PCI
        select FW_LOADER
        select MDIO
        ---help---
-         This driver supports Chelsio T4-based gigabit and 10Gb Ethernet
-         adapters.
+         This driver supports Chelsio T4 and T5 based gigabit, 10Gb Ethernet
+         adapter and T5 based 40Gb Ethernet adapter.
 
          For general information about Chelsio and our products, visit
          our website at <http://www.chelsio.com>.
@@ -87,11 +87,12 @@ config CHELSIO_T4
          will be called cxgb4.
 
 config CHELSIO_T4VF
-       tristate "Chelsio Communications T4 Virtual Function Ethernet support"
+       tristate "Chelsio Communications T4/T5 Virtual Function Ethernet support"
        depends on PCI
        ---help---
-         This driver supports Chelsio T4-based gigabit and 10Gb Ethernet
-         adapters with PCI-E SR-IOV Virtual Functions.
+         This driver supports Chelsio T4 and T5 based gigabit, 10Gb Ethernet
+         adapters and T5 based 40Gb Ethernet adapters with PCI-E SR-IOV Virtual
+         Functions.
 
          For general information about Chelsio and our products, visit
          our website at <http://www.chelsio.com>.
index 6fe58913403ab24f61ddf7f7e8d02714e040d250..24e16e3301e086d6cff3f28181d3c97a153bf343 100644 (file)
@@ -5870,6 +5870,8 @@ static void print_port_info(const struct net_device *dev)
                spd = " 2.5 GT/s";
        else if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_5_0GB)
                spd = " 5 GT/s";
+       else if (adap->params.pci.speed == PCI_EXP_LNKSTA_CLS_8_0GB)
+               spd = " 8 GT/s";
 
        if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_100M)
                bufp += sprintf(bufp, "100/");
diff --git a/drivers/net/ethernet/ec_bhf.c b/drivers/net/ethernet/ec_bhf.c
new file mode 100644 (file)
index 0000000..4884205
--- /dev/null
@@ -0,0 +1,706 @@
+ /*
+ * drivers/net/ethernet/beckhoff/ec_bhf.c
+ *
+ * Copyright (C) 2014 Darek Marcinkiewicz <reksio@newterm.pl>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+/* This is a driver for EtherCAT master module present on CCAT FPGA.
+ * Those can be found on Bechhoff CX50xx industrial PCs.
+ */
+
+#if 0
+#define DEBUG
+#endif
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/hrtimer.h>
+#include <linux/interrupt.h>
+#include <linux/stat.h>
+
+#define TIMER_INTERVAL_NSEC    20000
+
+#define INFO_BLOCK_SIZE                0x10
+#define INFO_BLOCK_TYPE                0x0
+#define INFO_BLOCK_REV         0x2
+#define INFO_BLOCK_BLK_CNT     0x4
+#define INFO_BLOCK_TX_CHAN     0x4
+#define INFO_BLOCK_RX_CHAN     0x5
+#define INFO_BLOCK_OFFSET      0x8
+
+#define EC_MII_OFFSET          0x4
+#define EC_FIFO_OFFSET         0x8
+#define EC_MAC_OFFSET          0xc
+
+#define MAC_FRAME_ERR_CNT      0x0
+#define MAC_RX_ERR_CNT         0x1
+#define MAC_CRC_ERR_CNT                0x2
+#define MAC_LNK_LST_ERR_CNT    0x3
+#define MAC_TX_FRAME_CNT       0x10
+#define MAC_RX_FRAME_CNT       0x14
+#define MAC_TX_FIFO_LVL                0x20
+#define MAC_DROPPED_FRMS       0x28
+#define MAC_CONNECTED_CCAT_FLAG        0x78
+
+#define MII_MAC_ADDR           0x8
+#define MII_MAC_FILT_FLAG      0xe
+#define MII_LINK_STATUS                0xf
+
+#define FIFO_TX_REG            0x0
+#define FIFO_TX_RESET          0x8
+#define FIFO_RX_REG            0x10
+#define FIFO_RX_ADDR_VALID     (1u << 31)
+#define FIFO_RX_RESET          0x18
+
+#define DMA_CHAN_OFFSET                0x1000
+#define DMA_CHAN_SIZE          0x8
+
+#define DMA_WINDOW_SIZE_MASK   0xfffffffc
+
+static struct pci_device_id ids[] = {
+       { PCI_DEVICE(0x15ec, 0x5000), },
+       { 0, }
+};
+MODULE_DEVICE_TABLE(pci, ids);
+
+struct rx_header {
+#define RXHDR_NEXT_ADDR_MASK   0xffffffu
+#define RXHDR_NEXT_VALID       (1u << 31)
+       __le32 next;
+#define RXHDR_NEXT_RECV_FLAG   0x1
+       __le32 recv;
+#define RXHDR_LEN_MASK         0xfffu
+       __le16 len;
+       __le16 port;
+       __le32 reserved;
+       u8 timestamp[8];
+} __packed;
+
+#define PKT_PAYLOAD_SIZE       0x7e8
+struct rx_desc {
+       struct rx_header header;
+       u8 data[PKT_PAYLOAD_SIZE];
+} __packed;
+
+struct tx_header {
+       __le16 len;
+#define TX_HDR_PORT_0          0x1
+#define TX_HDR_PORT_1          0x2
+       u8 port;
+       u8 ts_enable;
+#define TX_HDR_SENT            0x1
+       __le32 sent;
+       u8 timestamp[8];
+} __packed;
+
+struct tx_desc {
+       struct tx_header header;
+       u8 data[PKT_PAYLOAD_SIZE];
+} __packed;
+
+#define FIFO_SIZE              64
+
+static long polling_frequency = TIMER_INTERVAL_NSEC;
+
+struct bhf_dma {
+       u8 *buf;
+       size_t len;
+       dma_addr_t buf_phys;
+
+       u8 *alloc;
+       size_t alloc_len;
+       dma_addr_t alloc_phys;
+};
+
+struct ec_bhf_priv {
+       struct net_device *net_dev;
+
+       struct pci_dev *dev;
+
+       void * __iomem io;
+       void * __iomem dma_io;
+
+       struct hrtimer hrtimer;
+
+       int tx_dma_chan;
+       int rx_dma_chan;
+       void * __iomem ec_io;
+       void * __iomem fifo_io;
+       void * __iomem mii_io;
+       void * __iomem mac_io;
+
+       struct bhf_dma rx_buf;
+       struct rx_desc *rx_descs;
+       int rx_dnext;
+       int rx_dcount;
+
+       struct bhf_dma tx_buf;
+       struct tx_desc *tx_descs;
+       int tx_dcount;
+       int tx_dnext;
+
+       u64 stat_rx_bytes;
+       u64 stat_tx_bytes;
+};
+
+#define PRIV_TO_DEV(priv) (&(priv)->dev->dev)
+
+#define ETHERCAT_MASTER_ID     0x14
+
+static void ec_bhf_print_status(struct ec_bhf_priv *priv)
+{
+       struct device *dev = PRIV_TO_DEV(priv);
+
+       dev_dbg(dev, "Frame error counter: %d\n",
+               ioread8(priv->mac_io + MAC_FRAME_ERR_CNT));
+       dev_dbg(dev, "RX error counter: %d\n",
+               ioread8(priv->mac_io + MAC_RX_ERR_CNT));
+       dev_dbg(dev, "CRC error counter: %d\n",
+               ioread8(priv->mac_io + MAC_CRC_ERR_CNT));
+       dev_dbg(dev, "TX frame counter: %d\n",
+               ioread32(priv->mac_io + MAC_TX_FRAME_CNT));
+       dev_dbg(dev, "RX frame counter: %d\n",
+               ioread32(priv->mac_io + MAC_RX_FRAME_CNT));
+       dev_dbg(dev, "TX fifo level: %d\n",
+               ioread8(priv->mac_io + MAC_TX_FIFO_LVL));
+       dev_dbg(dev, "Dropped frames: %d\n",
+               ioread8(priv->mac_io + MAC_DROPPED_FRMS));
+       dev_dbg(dev, "Connected with CCAT slot: %d\n",
+               ioread8(priv->mac_io + MAC_CONNECTED_CCAT_FLAG));
+       dev_dbg(dev, "Link status: %d\n",
+               ioread8(priv->mii_io + MII_LINK_STATUS));
+}
+
+static void ec_bhf_reset(struct ec_bhf_priv *priv)
+{
+       iowrite8(0, priv->mac_io + MAC_FRAME_ERR_CNT);
+       iowrite8(0, priv->mac_io + MAC_RX_ERR_CNT);
+       iowrite8(0, priv->mac_io + MAC_CRC_ERR_CNT);
+       iowrite8(0, priv->mac_io + MAC_LNK_LST_ERR_CNT);
+       iowrite32(0, priv->mac_io + MAC_TX_FRAME_CNT);
+       iowrite32(0, priv->mac_io + MAC_RX_FRAME_CNT);
+       iowrite8(0, priv->mac_io + MAC_DROPPED_FRMS);
+
+       iowrite8(0, priv->fifo_io + FIFO_TX_RESET);
+       iowrite8(0, priv->fifo_io + FIFO_RX_RESET);
+
+       iowrite8(0, priv->mac_io + MAC_TX_FIFO_LVL);
+}
+
+static void ec_bhf_send_packet(struct ec_bhf_priv *priv, struct tx_desc *desc)
+{
+       u32 len = le16_to_cpu(desc->header.len) + sizeof(desc->header);
+       u32 addr = (u8 *)desc - priv->tx_buf.buf;
+
+       iowrite32((ALIGN(len, 8) << 24) | addr, priv->fifo_io + FIFO_TX_REG);
+
+       dev_dbg(PRIV_TO_DEV(priv), "Done sending packet\n");
+}
+
+static int ec_bhf_desc_sent(struct tx_desc *desc)
+{
+       return le32_to_cpu(desc->header.sent) & TX_HDR_SENT;
+}
+
+static void ec_bhf_process_tx(struct ec_bhf_priv *priv)
+{
+       if (unlikely(netif_queue_stopped(priv->net_dev))) {
+               /* Make sure that we perceive changes to tx_dnext. */
+               smp_rmb();
+
+               if (ec_bhf_desc_sent(&priv->tx_descs[priv->tx_dnext]))
+                       netif_wake_queue(priv->net_dev);
+       }
+}
+
+static int ec_bhf_pkt_received(struct rx_desc *desc)
+{
+       return le32_to_cpu(desc->header.recv) & RXHDR_NEXT_RECV_FLAG;
+}
+
+static void ec_bhf_add_rx_desc(struct ec_bhf_priv *priv, struct rx_desc *desc)
+{
+       iowrite32(FIFO_RX_ADDR_VALID | ((u8 *)(desc) - priv->rx_buf.buf),
+                 priv->fifo_io + FIFO_RX_REG);
+}
+
+static void ec_bhf_process_rx(struct ec_bhf_priv *priv)
+{
+       struct rx_desc *desc = &priv->rx_descs[priv->rx_dnext];
+       struct device *dev = PRIV_TO_DEV(priv);
+
+       while (ec_bhf_pkt_received(desc)) {
+               int pkt_size = (le16_to_cpu(desc->header.len) &
+                              RXHDR_LEN_MASK) - sizeof(struct rx_header) - 4;
+               u8 *data = desc->data;
+               struct sk_buff *skb;
+
+               skb = netdev_alloc_skb_ip_align(priv->net_dev, pkt_size);
+               dev_dbg(dev, "Received packet, size: %d\n", pkt_size);
+
+               if (skb) {
+                       memcpy(skb_put(skb, pkt_size), data, pkt_size);
+                       skb->protocol = eth_type_trans(skb, priv->net_dev);
+                       dev_dbg(dev, "Protocol type: %x\n", skb->protocol);
+
+                       priv->stat_rx_bytes += pkt_size;
+
+                       netif_rx(skb);
+               } else {
+                       dev_err_ratelimited(dev,
+                               "Couldn't allocate a skb_buff for a packet of size %u\n",
+                               pkt_size);
+               }
+
+               desc->header.recv = 0;
+
+               ec_bhf_add_rx_desc(priv, desc);
+
+               priv->rx_dnext = (priv->rx_dnext + 1) % priv->rx_dcount;
+               desc = &priv->rx_descs[priv->rx_dnext];
+       }
+
+}
+
+static enum hrtimer_restart ec_bhf_timer_fun(struct hrtimer *timer)
+{
+       struct ec_bhf_priv *priv = container_of(timer, struct ec_bhf_priv,
+                                               hrtimer);
+       ec_bhf_process_rx(priv);
+       ec_bhf_process_tx(priv);
+
+       if (!netif_running(priv->net_dev))
+               return HRTIMER_NORESTART;
+
+       hrtimer_forward_now(timer, ktime_set(0, polling_frequency));
+       return HRTIMER_RESTART;
+}
+
+static int ec_bhf_setup_offsets(struct ec_bhf_priv *priv)
+{
+       struct device *dev = PRIV_TO_DEV(priv);
+       unsigned block_count, i;
+       void * __iomem ec_info;
+
+       dev_dbg(dev, "Info block:\n");
+       dev_dbg(dev, "Type of function: %x\n", (unsigned)ioread16(priv->io));
+       dev_dbg(dev, "Revision of function: %x\n",
+               (unsigned)ioread16(priv->io + INFO_BLOCK_REV));
+
+       block_count = ioread8(priv->io + INFO_BLOCK_BLK_CNT);
+       dev_dbg(dev, "Number of function blocks: %x\n", block_count);
+
+       for (i = 0; i < block_count; i++) {
+               u16 type = ioread16(priv->io + i * INFO_BLOCK_SIZE +
+                                   INFO_BLOCK_TYPE);
+               if (type == ETHERCAT_MASTER_ID)
+                       break;
+       }
+       if (i == block_count) {
+               dev_err(dev, "EtherCAT master with DMA block not found\n");
+               return -ENODEV;
+       }
+       dev_dbg(dev, "EtherCAT master with DMA block found at pos: %d\n", i);
+
+       ec_info = priv->io + i * INFO_BLOCK_SIZE;
+       dev_dbg(dev, "EtherCAT master revision: %d\n",
+               ioread16(ec_info + INFO_BLOCK_REV));
+
+       priv->tx_dma_chan = ioread8(ec_info + INFO_BLOCK_TX_CHAN);
+       dev_dbg(dev, "EtherCAT master tx dma channel: %d\n",
+               priv->tx_dma_chan);
+
+       priv->rx_dma_chan = ioread8(ec_info + INFO_BLOCK_RX_CHAN);
+       dev_dbg(dev, "EtherCAT master rx dma channel: %d\n",
+                priv->rx_dma_chan);
+
+       priv->ec_io = priv->io + ioread32(ec_info + INFO_BLOCK_OFFSET);
+       priv->mii_io = priv->ec_io + ioread32(priv->ec_io + EC_MII_OFFSET);
+       priv->fifo_io = priv->ec_io + ioread32(priv->ec_io + EC_FIFO_OFFSET);
+       priv->mac_io = priv->ec_io + ioread32(priv->ec_io + EC_MAC_OFFSET);
+
+       dev_dbg(dev,
+               "EtherCAT block addres: %p, fifo address: %p, mii address: %p, mac address: %p\n",
+               priv->ec_io, priv->fifo_io, priv->mii_io, priv->mac_io);
+
+       return 0;
+}
+
+static netdev_tx_t ec_bhf_start_xmit(struct sk_buff *skb,
+                                    struct net_device *net_dev)
+{
+       struct ec_bhf_priv *priv = netdev_priv(net_dev);
+       struct tx_desc *desc;
+       unsigned len;
+
+       dev_dbg(PRIV_TO_DEV(priv), "Starting xmit\n");
+
+       desc = &priv->tx_descs[priv->tx_dnext];
+
+       skb_copy_and_csum_dev(skb, desc->data);
+       len = skb->len;
+
+       memset(&desc->header, 0, sizeof(desc->header));
+       desc->header.len = cpu_to_le16(len);
+       desc->header.port = TX_HDR_PORT_0;
+
+       ec_bhf_send_packet(priv, desc);
+
+       priv->tx_dnext = (priv->tx_dnext + 1) % priv->tx_dcount;
+
+       if (!ec_bhf_desc_sent(&priv->tx_descs[priv->tx_dnext])) {
+               /* Make sure that update updates to tx_dnext are perceived
+                * by timer routine.
+                */
+               smp_wmb();
+
+               netif_stop_queue(net_dev);
+
+               dev_dbg(PRIV_TO_DEV(priv), "Stopping netif queue\n");
+               ec_bhf_print_status(priv);
+       }
+
+       priv->stat_tx_bytes += len;
+
+       dev_kfree_skb(skb);
+
+       return NETDEV_TX_OK;
+}
+
+static int ec_bhf_alloc_dma_mem(struct ec_bhf_priv *priv,
+                               struct bhf_dma *buf,
+                               int channel,
+                               int size)
+{
+       int offset = channel * DMA_CHAN_SIZE + DMA_CHAN_OFFSET;
+       struct device *dev = PRIV_TO_DEV(priv);
+       u32 mask;
+
+       iowrite32(0xffffffff, priv->dma_io + offset);
+
+       mask = ioread32(priv->dma_io + offset);
+       mask &= DMA_WINDOW_SIZE_MASK;
+       dev_dbg(dev, "Read mask %x for channel %d\n", mask, channel);
+
+       /* We want to allocate a chunk of memory that is:
+        * - aligned to the mask we just read
+        * - is of size 2^mask bytes (at most)
+        * In order to ensure that we will allocate buffer of
+        * 2 * 2^mask bytes.
+        */
+       buf->len = min_t(int, ~mask + 1, size);
+       buf->alloc_len = 2 * buf->len;
+
+       dev_dbg(dev, "Allocating %d bytes for channel %d",
+               (int)buf->alloc_len, channel);
+       buf->alloc = dma_alloc_coherent(dev, buf->alloc_len, &buf->alloc_phys,
+                                       GFP_KERNEL);
+       if (buf->alloc == NULL) {
+               dev_info(dev, "Failed to allocate buffer\n");
+               return -ENOMEM;
+       }
+
+       buf->buf_phys = (buf->alloc_phys + buf->len) & mask;
+       buf->buf = buf->alloc + (buf->buf_phys - buf->alloc_phys);
+
+       iowrite32(0, priv->dma_io + offset + 4);
+       iowrite32(buf->buf_phys, priv->dma_io + offset);
+       dev_dbg(dev, "Buffer: %x and read from dev: %x",
+               (unsigned)buf->buf_phys, ioread32(priv->dma_io + offset));
+
+       return 0;
+}
+
+static void ec_bhf_setup_tx_descs(struct ec_bhf_priv *priv)
+{
+       int i = 0;
+
+       priv->tx_dcount = priv->tx_buf.len / sizeof(struct tx_desc);
+       priv->tx_descs = (struct tx_desc *) priv->tx_buf.buf;
+       priv->tx_dnext = 0;
+
+       for (i = 0; i < priv->tx_dcount; i++)
+               priv->tx_descs[i].header.sent = cpu_to_le32(TX_HDR_SENT);
+}
+
+static void ec_bhf_setup_rx_descs(struct ec_bhf_priv *priv)
+{
+       int i;
+
+       priv->rx_dcount = priv->rx_buf.len / sizeof(struct rx_desc);
+       priv->rx_descs = (struct rx_desc *) priv->rx_buf.buf;
+       priv->rx_dnext = 0;
+
+       for (i = 0; i < priv->rx_dcount; i++) {
+               struct rx_desc *desc = &priv->rx_descs[i];
+               u32 next;
+
+               if (i != priv->rx_dcount - 1)
+                       next = (u8 *)(desc + 1) - priv->rx_buf.buf;
+               else
+                       next = 0;
+               next |= RXHDR_NEXT_VALID;
+               desc->header.next = cpu_to_le32(next);
+               desc->header.recv = 0;
+               ec_bhf_add_rx_desc(priv, desc);
+       }
+}
+
+static int ec_bhf_open(struct net_device *net_dev)
+{
+       struct ec_bhf_priv *priv = netdev_priv(net_dev);
+       struct device *dev = PRIV_TO_DEV(priv);
+       int err = 0;
+
+       dev_info(dev, "Opening device\n");
+
+       ec_bhf_reset(priv);
+
+       err = ec_bhf_alloc_dma_mem(priv, &priv->rx_buf, priv->rx_dma_chan,
+                                  FIFO_SIZE * sizeof(struct rx_desc));
+       if (err) {
+               dev_err(dev, "Failed to allocate rx buffer\n");
+               goto out;
+       }
+       ec_bhf_setup_rx_descs(priv);
+
+       dev_info(dev, "RX buffer allocated, address: %x\n",
+                (unsigned)priv->rx_buf.buf_phys);
+
+       err = ec_bhf_alloc_dma_mem(priv, &priv->tx_buf, priv->tx_dma_chan,
+                                  FIFO_SIZE * sizeof(struct tx_desc));
+       if (err) {
+               dev_err(dev, "Failed to allocate tx buffer\n");
+               goto error_rx_free;
+       }
+       dev_dbg(dev, "TX buffer allocated, addres: %x\n",
+               (unsigned)priv->tx_buf.buf_phys);
+
+       iowrite8(0, priv->mii_io + MII_MAC_FILT_FLAG);
+
+       ec_bhf_setup_tx_descs(priv);
+
+       netif_start_queue(net_dev);
+
+       hrtimer_init(&priv->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       priv->hrtimer.function = ec_bhf_timer_fun;
+       hrtimer_start(&priv->hrtimer, ktime_set(0, polling_frequency),
+                     HRTIMER_MODE_REL);
+
+       dev_info(PRIV_TO_DEV(priv), "Device open\n");
+
+       ec_bhf_print_status(priv);
+
+       return 0;
+
+error_rx_free:
+       dma_free_coherent(dev, priv->rx_buf.alloc_len, priv->rx_buf.alloc,
+                         priv->rx_buf.alloc_len);
+out:
+       return err;
+}
+
+static int ec_bhf_stop(struct net_device *net_dev)
+{
+       struct ec_bhf_priv *priv = netdev_priv(net_dev);
+       struct device *dev = PRIV_TO_DEV(priv);
+
+       hrtimer_cancel(&priv->hrtimer);
+
+       ec_bhf_reset(priv);
+
+       netif_tx_disable(net_dev);
+
+       dma_free_coherent(dev, priv->tx_buf.alloc_len,
+                         priv->tx_buf.alloc, priv->tx_buf.alloc_phys);
+       dma_free_coherent(dev, priv->rx_buf.alloc_len,
+                         priv->rx_buf.alloc, priv->rx_buf.alloc_phys);
+
+       return 0;
+}
+
+static struct rtnl_link_stats64 *
+ec_bhf_get_stats(struct net_device *net_dev,
+                struct rtnl_link_stats64 *stats)
+{
+       struct ec_bhf_priv *priv = netdev_priv(net_dev);
+
+       stats->rx_errors = ioread8(priv->mac_io + MAC_RX_ERR_CNT) +
+                               ioread8(priv->mac_io + MAC_CRC_ERR_CNT) +
+                               ioread8(priv->mac_io + MAC_FRAME_ERR_CNT);
+       stats->rx_packets = ioread32(priv->mac_io + MAC_RX_FRAME_CNT);
+       stats->tx_packets = ioread32(priv->mac_io + MAC_TX_FRAME_CNT);
+       stats->rx_dropped = ioread8(priv->mac_io + MAC_DROPPED_FRMS);
+
+       stats->tx_bytes = priv->stat_tx_bytes;
+       stats->rx_bytes = priv->stat_rx_bytes;
+
+       return stats;
+}
+
+static const struct net_device_ops ec_bhf_netdev_ops = {
+       .ndo_start_xmit         = ec_bhf_start_xmit,
+       .ndo_open               = ec_bhf_open,
+       .ndo_stop               = ec_bhf_stop,
+       .ndo_get_stats64        = ec_bhf_get_stats,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr
+};
+
+static int ec_bhf_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       struct net_device *net_dev;
+       struct ec_bhf_priv *priv;
+       void * __iomem dma_io;
+       void * __iomem io;
+       int err = 0;
+
+       err = pci_enable_device(dev);
+       if (err)
+               return err;
+
+       pci_set_master(dev);
+
+       err = pci_set_dma_mask(dev, DMA_BIT_MASK(32));
+       if (err) {
+               dev_err(&dev->dev,
+                       "Required dma mask not supported, failed to initialize device\n");
+               err = -EIO;
+               goto err_disable_dev;
+       }
+
+       err = pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(32));
+       if (err) {
+               dev_err(&dev->dev,
+                       "Required dma mask not supported, failed to initialize device\n");
+               goto err_disable_dev;
+       }
+
+       err = pci_request_regions(dev, "ec_bhf");
+       if (err) {
+               dev_err(&dev->dev, "Failed to request pci memory regions\n");
+               goto err_disable_dev;
+       }
+
+       io = pci_iomap(dev, 0, 0);
+       if (!io) {
+               dev_err(&dev->dev, "Failed to map pci card memory bar 0");
+               err = -EIO;
+               goto err_release_regions;
+       }
+
+       dma_io = pci_iomap(dev, 2, 0);
+       if (!dma_io) {
+               dev_err(&dev->dev, "Failed to map pci card memory bar 2");
+               err = -EIO;
+               goto err_unmap;
+       }
+
+       net_dev = alloc_etherdev(sizeof(struct ec_bhf_priv));
+       if (net_dev == 0) {
+               err = -ENOMEM;
+               goto err_unmap_dma_io;
+       }
+
+       pci_set_drvdata(dev, net_dev);
+       SET_NETDEV_DEV(net_dev, &dev->dev);
+
+       net_dev->features = 0;
+       net_dev->flags |= IFF_NOARP;
+
+       net_dev->netdev_ops = &ec_bhf_netdev_ops;
+
+       priv = netdev_priv(net_dev);
+       priv->net_dev = net_dev;
+       priv->io = io;
+       priv->dma_io = dma_io;
+       priv->dev = dev;
+
+       err = ec_bhf_setup_offsets(priv);
+       if (err < 0)
+               goto err_free_net_dev;
+
+       memcpy_fromio(net_dev->dev_addr, priv->mii_io + MII_MAC_ADDR, 6);
+
+       dev_dbg(&dev->dev, "CX5020 Ethercat master address: %pM\n",
+               net_dev->dev_addr);
+
+       err = register_netdev(net_dev);
+       if (err < 0)
+               goto err_free_net_dev;
+
+       return 0;
+
+err_free_net_dev:
+       free_netdev(net_dev);
+err_unmap_dma_io:
+       pci_iounmap(dev, dma_io);
+err_unmap:
+       pci_iounmap(dev, io);
+err_release_regions:
+       pci_release_regions(dev);
+err_disable_dev:
+       pci_clear_master(dev);
+       pci_disable_device(dev);
+
+       return err;
+}
+
+static void ec_bhf_remove(struct pci_dev *dev)
+{
+       struct net_device *net_dev = pci_get_drvdata(dev);
+       struct ec_bhf_priv *priv = netdev_priv(net_dev);
+
+       unregister_netdev(net_dev);
+       free_netdev(net_dev);
+
+       pci_iounmap(dev, priv->dma_io);
+       pci_iounmap(dev, priv->io);
+       pci_release_regions(dev);
+       pci_clear_master(dev);
+       pci_disable_device(dev);
+}
+
+static struct pci_driver pci_driver = {
+       .name           = "ec_bhf",
+       .id_table       = ids,
+       .probe          = ec_bhf_probe,
+       .remove         = ec_bhf_remove,
+};
+
+static int __init ec_bhf_init(void)
+{
+       return pci_register_driver(&pci_driver);
+}
+
+static void __exit ec_bhf_exit(void)
+{
+       pci_unregister_driver(&pci_driver);
+}
+
+module_init(ec_bhf_init);
+module_exit(ec_bhf_exit);
+
+module_param(polling_frequency, long, S_IRUGO);
+MODULE_PARM_DESC(polling_frequency, "Polling timer frequency in ns");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Dariusz Marcinkiewicz <reksio@newterm.pl>");
index a18645407d2152b43353a50b76ccf6317ef90151..dc19bc5dec7732c02220e009ad08ffc393aa1c2c 100644 (file)
@@ -4949,6 +4949,12 @@ static void be_eeh_resume(struct pci_dev *pdev)
        if (status)
                goto err;
 
+       /* On some BE3 FW versions, after a HW reset,
+        * interrupts will remain disabled for each function.
+        * So, explicitly enable interrupts
+        */
+       be_intr_set(adapter, true);
+
        /* tell fw we're ready to fire cmds */
        status = be_cmd_fw_init(adapter);
        if (status)
index 9125d9abf0998d31e3179bd9c712af487855d5a9..e2d42475b006aa7a79f16b48ad618580d64c7593 100644 (file)
@@ -121,6 +121,7 @@ static irqreturn_t gfar_error(int irq, void *dev_id);
 static irqreturn_t gfar_transmit(int irq, void *dev_id);
 static irqreturn_t gfar_interrupt(int irq, void *dev_id);
 static void adjust_link(struct net_device *dev);
+static noinline void gfar_update_link_state(struct gfar_private *priv);
 static int init_phy(struct net_device *dev);
 static int gfar_probe(struct platform_device *ofdev);
 static int gfar_remove(struct platform_device *ofdev);
@@ -3076,41 +3077,6 @@ static irqreturn_t gfar_interrupt(int irq, void *grp_id)
        return IRQ_HANDLED;
 }
 
-static u32 gfar_get_flowctrl_cfg(struct gfar_private *priv)
-{
-       struct phy_device *phydev = priv->phydev;
-       u32 val = 0;
-
-       if (!phydev->duplex)
-               return val;
-
-       if (!priv->pause_aneg_en) {
-               if (priv->tx_pause_en)
-                       val |= MACCFG1_TX_FLOW;
-               if (priv->rx_pause_en)
-                       val |= MACCFG1_RX_FLOW;
-       } else {
-               u16 lcl_adv, rmt_adv;
-               u8 flowctrl;
-               /* get link partner capabilities */
-               rmt_adv = 0;
-               if (phydev->pause)
-                       rmt_adv = LPA_PAUSE_CAP;
-               if (phydev->asym_pause)
-                       rmt_adv |= LPA_PAUSE_ASYM;
-
-               lcl_adv = mii_advertise_flowctrl(phydev->advertising);
-
-               flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
-               if (flowctrl & FLOW_CTRL_TX)
-                       val |= MACCFG1_TX_FLOW;
-               if (flowctrl & FLOW_CTRL_RX)
-                       val |= MACCFG1_RX_FLOW;
-       }
-
-       return val;
-}
-
 /* Called every time the controller might need to be made
  * aware of new link state.  The PHY code conveys this
  * information through variables in the phydev structure, and this
@@ -3120,83 +3086,12 @@ static u32 gfar_get_flowctrl_cfg(struct gfar_private *priv)
 static void adjust_link(struct net_device *dev)
 {
        struct gfar_private *priv = netdev_priv(dev);
-       struct gfar __iomem *regs = priv->gfargrp[0].regs;
        struct phy_device *phydev = priv->phydev;
-       int new_state = 0;
 
-       if (test_bit(GFAR_RESETTING, &priv->state))
-               return;
-
-       if (phydev->link) {
-               u32 tempval1 = gfar_read(&regs->maccfg1);
-               u32 tempval = gfar_read(&regs->maccfg2);
-               u32 ecntrl = gfar_read(&regs->ecntrl);
-
-               /* Now we make sure that we can be in full duplex mode.
-                * If not, we operate in half-duplex mode.
-                */
-               if (phydev->duplex != priv->oldduplex) {
-                       new_state = 1;
-                       if (!(phydev->duplex))
-                               tempval &= ~(MACCFG2_FULL_DUPLEX);
-                       else
-                               tempval |= MACCFG2_FULL_DUPLEX;
-
-                       priv->oldduplex = phydev->duplex;
-               }
-
-               if (phydev->speed != priv->oldspeed) {
-                       new_state = 1;
-                       switch (phydev->speed) {
-                       case 1000:
-                               tempval =
-                                   ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII);
-
-                               ecntrl &= ~(ECNTRL_R100);
-                               break;
-                       case 100:
-                       case 10:
-                               tempval =
-                                   ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII);
-
-                               /* Reduced mode distinguishes
-                                * between 10 and 100
-                                */
-                               if (phydev->speed == SPEED_100)
-                                       ecntrl |= ECNTRL_R100;
-                               else
-                                       ecntrl &= ~(ECNTRL_R100);
-                               break;
-                       default:
-                               netif_warn(priv, link, dev,
-                                          "Ack!  Speed (%d) is not 10/100/1000!\n",
-                                          phydev->speed);
-                               break;
-                       }
-
-                       priv->oldspeed = phydev->speed;
-               }
-
-               tempval1 &= ~(MACCFG1_TX_FLOW | MACCFG1_RX_FLOW);
-               tempval1 |= gfar_get_flowctrl_cfg(priv);
-
-               gfar_write(&regs->maccfg1, tempval1);
-               gfar_write(&regs->maccfg2, tempval);
-               gfar_write(&regs->ecntrl, ecntrl);
-
-               if (!priv->oldlink) {
-                       new_state = 1;
-                       priv->oldlink = 1;
-               }
-       } else if (priv->oldlink) {
-               new_state = 1;
-               priv->oldlink = 0;
-               priv->oldspeed = 0;
-               priv->oldduplex = -1;
-       }
-
-       if (new_state && netif_msg_link(priv))
-               phy_print_status(phydev);
+       if (unlikely(phydev->link != priv->oldlink ||
+                    phydev->duplex != priv->oldduplex ||
+                    phydev->speed != priv->oldspeed))
+               gfar_update_link_state(priv);
 }
 
 /* Update the hash table based on the current list of multicast
@@ -3442,6 +3337,114 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
        return IRQ_HANDLED;
 }
 
+static u32 gfar_get_flowctrl_cfg(struct gfar_private *priv)
+{
+       struct phy_device *phydev = priv->phydev;
+       u32 val = 0;
+
+       if (!phydev->duplex)
+               return val;
+
+       if (!priv->pause_aneg_en) {
+               if (priv->tx_pause_en)
+                       val |= MACCFG1_TX_FLOW;
+               if (priv->rx_pause_en)
+                       val |= MACCFG1_RX_FLOW;
+       } else {
+               u16 lcl_adv, rmt_adv;
+               u8 flowctrl;
+               /* get link partner capabilities */
+               rmt_adv = 0;
+               if (phydev->pause)
+                       rmt_adv = LPA_PAUSE_CAP;
+               if (phydev->asym_pause)
+                       rmt_adv |= LPA_PAUSE_ASYM;
+
+               lcl_adv = mii_advertise_flowctrl(phydev->advertising);
+
+               flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
+               if (flowctrl & FLOW_CTRL_TX)
+                       val |= MACCFG1_TX_FLOW;
+               if (flowctrl & FLOW_CTRL_RX)
+                       val |= MACCFG1_RX_FLOW;
+       }
+
+       return val;
+}
+
+static noinline void gfar_update_link_state(struct gfar_private *priv)
+{
+       struct gfar __iomem *regs = priv->gfargrp[0].regs;
+       struct phy_device *phydev = priv->phydev;
+
+       if (unlikely(test_bit(GFAR_RESETTING, &priv->state)))
+               return;
+
+       if (phydev->link) {
+               u32 tempval1 = gfar_read(&regs->maccfg1);
+               u32 tempval = gfar_read(&regs->maccfg2);
+               u32 ecntrl = gfar_read(&regs->ecntrl);
+
+               if (phydev->duplex != priv->oldduplex) {
+                       if (!(phydev->duplex))
+                               tempval &= ~(MACCFG2_FULL_DUPLEX);
+                       else
+                               tempval |= MACCFG2_FULL_DUPLEX;
+
+                       priv->oldduplex = phydev->duplex;
+               }
+
+               if (phydev->speed != priv->oldspeed) {
+                       switch (phydev->speed) {
+                       case 1000:
+                               tempval =
+                                   ((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII);
+
+                               ecntrl &= ~(ECNTRL_R100);
+                               break;
+                       case 100:
+                       case 10:
+                               tempval =
+                                   ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII);
+
+                               /* Reduced mode distinguishes
+                                * between 10 and 100
+                                */
+                               if (phydev->speed == SPEED_100)
+                                       ecntrl |= ECNTRL_R100;
+                               else
+                                       ecntrl &= ~(ECNTRL_R100);
+                               break;
+                       default:
+                               netif_warn(priv, link, priv->ndev,
+                                          "Ack!  Speed (%d) is not 10/100/1000!\n",
+                                          phydev->speed);
+                               break;
+                       }
+
+                       priv->oldspeed = phydev->speed;
+               }
+
+               tempval1 &= ~(MACCFG1_TX_FLOW | MACCFG1_RX_FLOW);
+               tempval1 |= gfar_get_flowctrl_cfg(priv);
+
+               gfar_write(&regs->maccfg1, tempval1);
+               gfar_write(&regs->maccfg2, tempval);
+               gfar_write(&regs->ecntrl, ecntrl);
+
+               if (!priv->oldlink)
+                       priv->oldlink = 1;
+
+       } else if (priv->oldlink) {
+               priv->oldlink = 0;
+               priv->oldspeed = 0;
+               priv->oldduplex = -1;
+       }
+
+       if (netif_msg_link(priv))
+               phy_print_status(phydev);
+}
+
 static struct of_device_id gfar_match[] =
 {
        {
index 891dbee6e6c14d2394cc2dff00092f448faf3dc2..76d70708f864af66b4a525e671f021e0d30a2b7d 100644 (file)
@@ -533,6 +533,9 @@ static int gfar_spauseparam(struct net_device *dev,
        struct gfar __iomem *regs = priv->gfargrp[0].regs;
        u32 oldadv, newadv;
 
+       if (!phydev)
+               return -ENODEV;
+
        if (!(phydev->supported & SUPPORTED_Pause) ||
            (!(phydev->supported & SUPPORTED_Asym_Pause) &&
             (epause->rx_pause != epause->tx_pause)))
index 9866f264f55e33a8e564757730ada0d6ab7c6a92..f0bbd4246d71d857eba4c439cac33e0c8a930864 100644 (file)
@@ -186,7 +186,7 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
 {
        u16 phy_reg = 0;
        u32 phy_id = 0;
-       s32 ret_val;
+       s32 ret_val = 0;
        u16 retry_count;
        u32 mac_reg = 0;
 
@@ -217,11 +217,13 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
        /* In case the PHY needs to be in mdio slow mode,
         * set slow mode and try to get the PHY id again.
         */
-       hw->phy.ops.release(hw);
-       ret_val = e1000_set_mdio_slow_mode_hv(hw);
-       if (!ret_val)
-               ret_val = e1000e_get_phy_id(hw);
-       hw->phy.ops.acquire(hw);
+       if (hw->mac.type < e1000_pch_lpt) {
+               hw->phy.ops.release(hw);
+               ret_val = e1000_set_mdio_slow_mode_hv(hw);
+               if (!ret_val)
+                       ret_val = e1000e_get_phy_id(hw);
+               hw->phy.ops.acquire(hw);
+       }
 
        if (ret_val)
                return false;
@@ -842,6 +844,17 @@ s32 e1000_set_eee_pchlan(struct e1000_hw *hw)
                }
        }
 
+       if (hw->phy.type == e1000_phy_82579) {
+               ret_val = e1000_read_emi_reg_locked(hw, I82579_LPI_PLL_SHUT,
+                                                   &data);
+               if (ret_val)
+                       goto release;
+
+               data &= ~I82579_LPI_100_PLL_SHUT;
+               ret_val = e1000_write_emi_reg_locked(hw, I82579_LPI_PLL_SHUT,
+                                                    data);
+       }
+
        /* R/Clr IEEE MMD 3.1 bits 11:10 - Tx/Rx LPI Received */
        ret_val = e1000_read_emi_reg_locked(hw, pcs_status, &data);
        if (ret_val)
@@ -1314,14 +1327,17 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
                        return ret_val;
        }
 
-       /* When connected at 10Mbps half-duplex, 82579 parts are excessively
+       /* When connected at 10Mbps half-duplex, some parts are excessively
         * aggressive resulting in many collisions. To avoid this, increase
         * the IPG and reduce Rx latency in the PHY.
         */
-       if ((hw->mac.type == e1000_pch2lan) && link) {
+       if (((hw->mac.type == e1000_pch2lan) ||
+            (hw->mac.type == e1000_pch_lpt)) && link) {
                u32 reg;
                reg = er32(STATUS);
                if (!(reg & (E1000_STATUS_FD | E1000_STATUS_SPEED_MASK))) {
+                       u16 emi_addr;
+
                        reg = er32(TIPG);
                        reg &= ~E1000_TIPG_IPGT_MASK;
                        reg |= 0xFF;
@@ -1332,8 +1348,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
                        if (ret_val)
                                return ret_val;
 
-                       ret_val =
-                           e1000_write_emi_reg_locked(hw, I82579_RX_CONFIG, 0);
+                       if (hw->mac.type == e1000_pch2lan)
+                               emi_addr = I82579_RX_CONFIG;
+                       else
+                               emi_addr = I217_RX_CONFIG;
+
+                       ret_val = e1000_write_emi_reg_locked(hw, emi_addr, 0);
 
                        hw->phy.ops.release(hw);
 
@@ -2493,51 +2513,44 @@ release:
  *  e1000_k1_gig_workaround_lv - K1 Si workaround
  *  @hw:   pointer to the HW structure
  *
- *  Workaround to set the K1 beacon duration for 82579 parts
+ *  Workaround to set the K1 beacon duration for 82579 parts in 10Mbps
+ *  Disable K1 in 1000Mbps and 100Mbps
  **/
 static s32 e1000_k1_workaround_lv(struct e1000_hw *hw)
 {
        s32 ret_val = 0;
        u16 status_reg = 0;
-       u32 mac_reg;
-       u16 phy_reg;
 
        if (hw->mac.type != e1000_pch2lan)
                return 0;
 
-       /* Set K1 beacon duration based on 1Gbps speed or otherwise */
+       /* Set K1 beacon duration based on 10Mbs speed */
        ret_val = e1e_rphy(hw, HV_M_STATUS, &status_reg);
        if (ret_val)
                return ret_val;
 
        if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE))
            == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) {
-               mac_reg = er32(FEXTNVM4);
-               mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK;
-
-               ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg);
-               if (ret_val)
-                       return ret_val;
-
-               if (status_reg & HV_M_STATUS_SPEED_1000) {
+               if (status_reg &
+                   (HV_M_STATUS_SPEED_1000 | HV_M_STATUS_SPEED_100)) {
                        u16 pm_phy_reg;
 
-                       mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC;
-                       phy_reg &= ~I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT;
-                       /* LV 1G Packet drop issue wa  */
+                       /* LV 1G/100 Packet drop issue wa  */
                        ret_val = e1e_rphy(hw, HV_PM_CTRL, &pm_phy_reg);
                        if (ret_val)
                                return ret_val;
-                       pm_phy_reg &= ~HV_PM_CTRL_PLL_STOP_IN_K1_GIGA;
+                       pm_phy_reg &= ~HV_PM_CTRL_K1_ENABLE;
                        ret_val = e1e_wphy(hw, HV_PM_CTRL, pm_phy_reg);
                        if (ret_val)
                                return ret_val;
                } else {
+                       u32 mac_reg;
+
+                       mac_reg = er32(FEXTNVM4);
+                       mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK;
                        mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC;
-                       phy_reg |= I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT;
+                       ew32(FEXTNVM4, mac_reg);
                }
-               ew32(FEXTNVM4, mac_reg);
-               ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg);
        }
 
        return ret_val;
index bead50f9187b527291596da67351339b64482707..5515126c81c199b5e44bd909ac9ea3f336cf4fcd 100644 (file)
 #define I82577_MSE_THRESHOLD   0x0887  /* 82577 Mean Square Error Threshold */
 #define I82579_MSE_LINK_DOWN   0x2411  /* MSE count before dropping link */
 #define I82579_RX_CONFIG               0x3412  /* Receive configuration */
+#define I82579_LPI_PLL_SHUT            0x4412  /* LPI PLL Shut Enable */
 #define I82579_EEE_PCS_STATUS          0x182E  /* IEEE MMD Register 3.1 >> 8 */
 #define I82579_EEE_CAPABILITY          0x0410  /* IEEE MMD Register 3.20 */
 #define I82579_EEE_ADVERTISEMENT       0x040E  /* IEEE MMD Register 7.60 */
 #define I82579_EEE_LP_ABILITY          0x040F  /* IEEE MMD Register 7.61 */
 #define I82579_EEE_100_SUPPORTED       (1 << 1)        /* 100BaseTx EEE */
 #define I82579_EEE_1000_SUPPORTED      (1 << 2)        /* 1000BaseTx EEE */
+#define I82579_LPI_100_PLL_SHUT        (1 << 2)        /* 100M LPI PLL Shut Enabled */
 #define I217_EEE_PCS_STATUS    0x9401  /* IEEE MMD Register 3.1 */
 #define I217_EEE_CAPABILITY    0x8000  /* IEEE MMD Register 3.20 */
 #define I217_EEE_ADVERTISEMENT 0x8001  /* IEEE MMD Register 7.60 */
 #define I217_EEE_LP_ABILITY    0x8002  /* IEEE MMD Register 7.61 */
+#define I217_RX_CONFIG         0xB20C  /* Receive configuration */
 
 #define E1000_EEE_RX_LPI_RCVD  0x0400  /* Tx LP idle received */
 #define E1000_EEE_TX_LPI_RCVD  0x0800  /* Rx LP idle received */
index d50c91e5052808b9485a44538e4b0821b9b30e88..3e69386add04ab43bc083d92411734320fc9845f 100644 (file)
@@ -1165,7 +1165,7 @@ static void e1000e_tx_hwtstamp_work(struct work_struct *work)
                dev_kfree_skb_any(adapter->tx_hwtstamp_skb);
                adapter->tx_hwtstamp_skb = NULL;
                adapter->tx_hwtstamp_timeouts++;
-               e_warn("clearing Tx timestamp hang");
+               e_warn("clearing Tx timestamp hang\n");
        } else {
                /* reschedule to check later */
                schedule_work(&adapter->tx_hwtstamp_work);
@@ -5687,7 +5687,7 @@ struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev,
 static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
-       int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
+       int max_frame = new_mtu + VLAN_HLEN + ETH_HLEN + ETH_FCS_LEN;
 
        /* Jumbo frame support */
        if ((max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) &&
@@ -6235,6 +6235,7 @@ static int __e1000_resume(struct pci_dev *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int e1000e_pm_thaw(struct device *dev)
 {
        struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
@@ -6255,7 +6256,6 @@ static int e1000e_pm_thaw(struct device *dev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
 static int e1000e_pm_suspend(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
index 3841bccf058c7aa0fe3b2f90e2c70c38e9b6f209..537d2780b408b3cdc9e0fc546d45c04444cc86e2 100644 (file)
@@ -164,6 +164,7 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw);
 #define HV_M_STATUS_AUTONEG_COMPLETE   0x1000
 #define HV_M_STATUS_SPEED_MASK         0x0300
 #define HV_M_STATUS_SPEED_1000         0x0200
+#define HV_M_STATUS_SPEED_100          0x0100
 #define HV_M_STATUS_LINK_UP            0x0040
 
 #define IGP01E1000_PHY_PCS_INIT_REG    0x00B4
index 861b722c2672e78b0ed0ccbe2cdd2f4428d8f472..cf0761f08911b5e8946871fa9e522f57b2de5c82 100644 (file)
@@ -2897,12 +2897,9 @@ static irqreturn_t i40e_intr(int irq, void *data)
                u32 prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_0);
 
                if (prttsyn_stat & I40E_PRTTSYN_STAT_0_TXTIME_MASK) {
-                       ena_mask &= ~I40E_PFINT_ICR0_ENA_TIMESYNC_MASK;
+                       icr0 &= ~I40E_PFINT_ICR0_ENA_TIMESYNC_MASK;
                        i40e_ptp_tx_hwtstamp(pf);
-                       prttsyn_stat &= ~I40E_PRTTSYN_STAT_0_TXTIME_MASK;
                }
-
-               wr32(hw, I40E_PRTTSYN_STAT_0, prttsyn_stat);
        }
 
        /* If a critical error is pending we have no choice but to reset the
@@ -4271,6 +4268,14 @@ static int i40e_open(struct net_device *netdev)
        if (err)
                return err;
 
+       /* configure global TSO hardware offload settings */
+       wr32(&pf->hw, I40E_GLLAN_TSOMSK_F, be32_to_cpu(TCP_FLAG_PSH |
+                                                      TCP_FLAG_FIN) >> 16);
+       wr32(&pf->hw, I40E_GLLAN_TSOMSK_M, be32_to_cpu(TCP_FLAG_PSH |
+                                                      TCP_FLAG_FIN |
+                                                      TCP_FLAG_CWR) >> 16);
+       wr32(&pf->hw, I40E_GLLAN_TSOMSK_L, be32_to_cpu(TCP_FLAG_CWR) >> 16);
+
 #ifdef CONFIG_I40E_VXLAN
        vxlan_get_rx_port(netdev);
 #endif
@@ -6712,6 +6717,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
                           NETIF_F_HW_VLAN_CTAG_FILTER |
                           NETIF_F_IPV6_CSUM           |
                           NETIF_F_TSO                 |
+                          NETIF_F_TSO_ECN             |
                           NETIF_F_TSO6                |
                           NETIF_F_RXCSUM              |
                           NETIF_F_NTUPLE              |
index 262bdf11d221e5a30be53a2f57a09e1865b32e79..81299189a47d3e58b61e75dba58869a85e813f2e 100644 (file)
@@ -160,7 +160,7 @@ static i40e_status i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw)
                udelay(5);
        }
        if (ret_code == I40E_ERR_TIMEOUT)
-               hw_dbg(hw, "Done bit in GLNVM_SRCTL not set");
+               hw_dbg(hw, "Done bit in GLNVM_SRCTL not set\n");
        return ret_code;
 }
 
index e33ec6c842b7035acd8189520a4f410c495270f1..e61e63720800fcbcc9c13b269f531b65e3902d7e 100644 (file)
@@ -239,7 +239,7 @@ static void i40e_ptp_tx_work(struct work_struct *work)
                dev_kfree_skb_any(pf->ptp_tx_skb);
                pf->ptp_tx_skb = NULL;
                pf->tx_hwtstamp_timeouts++;
-               dev_warn(&pf->pdev->dev, "clearing Tx timestamp hang");
+               dev_warn(&pf->pdev->dev, "clearing Tx timestamp hang\n");
                return;
        }
 
@@ -321,7 +321,7 @@ void i40e_ptp_rx_hang(struct i40e_vsi *vsi)
                pf->last_rx_ptp_check = jiffies;
                pf->rx_hwtstamp_cleared++;
                dev_warn(&vsi->back->pdev->dev,
-                        "%s: clearing Rx timestamp hang",
+                        "%s: clearing Rx timestamp hang\n",
                         __func__);
        }
 }
index 0f5d96ad281d2400cbe4fbc47e886f9832758e4b..9478ddc66caf8d71cfecd6c322e635d247e3fd95 100644 (file)
@@ -418,7 +418,7 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi,
                }
                break;
        default:
-               dev_info(&pf->pdev->dev, "Could not specify spec type %d",
+               dev_info(&pf->pdev->dev, "Could not specify spec type %d\n",
                         input->flow_type);
                ret = -EINVAL;
        }
@@ -478,7 +478,7 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring,
                                pf->flags |= I40E_FLAG_FDIR_REQUIRES_REINIT;
                        }
                } else {
-                       dev_info(&pdev->dev, "FD filter programming error");
+                       dev_info(&pdev->dev, "FD filter programming error\n");
                }
        } else if (error ==
                          (0x1 << I40E_RX_PROG_STATUS_DESC_NO_FD_ENTRY_SHIFT)) {
@@ -1713,9 +1713,11 @@ static int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
                                I40E_TX_FLAGS_VLAN_PRIO_SHIFT;
                if (tx_flags & I40E_TX_FLAGS_SW_VLAN) {
                        struct vlan_ethhdr *vhdr;
-                       if (skb_header_cloned(skb) &&
-                           pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
-                               return -ENOMEM;
+                       int rc;
+
+                       rc = skb_cow_head(skb, 0);
+                       if (rc < 0)
+                               return rc;
                        vhdr = (struct vlan_ethhdr *)skb->data;
                        vhdr->h_vlan_TCI = htons(tx_flags >>
                                                 I40E_TX_FLAGS_VLAN_SHIFT);
@@ -1743,20 +1745,18 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb,
                    u64 *cd_type_cmd_tso_mss, u32 *cd_tunneling)
 {
        u32 cd_cmd, cd_tso_len, cd_mss;
+       struct ipv6hdr *ipv6h;
        struct tcphdr *tcph;
        struct iphdr *iph;
        u32 l4len;
        int err;
-       struct ipv6hdr *ipv6h;
 
        if (!skb_is_gso(skb))
                return 0;
 
-       if (skb_header_cloned(skb)) {
-               err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
-               if (err)
-                       return err;
-       }
+       err = skb_cow_head(skb, 0);
+       if (err < 0)
+               return err;
 
        if (protocol == htons(ETH_P_IP)) {
                iph = skb->encapsulation ? inner_ip_hdr(skb) : ip_hdr(skb);
index db963397cc27f42fd15829ec6dc540e19af5f562..f67f8a170b90c81bcf4738154f1f7cead7171992 100644 (file)
@@ -365,7 +365,7 @@ static s32 igb_read_invm_word_i210(struct e1000_hw *hw, u8 address, u16 *data)
                        word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
                        if (word_address == address) {
                                *data = INVM_DWORD_TO_WORD_DATA(invm_dword);
-                               hw_dbg("Read INVM Word 0x%02x = %x",
+                               hw_dbg("Read INVM Word 0x%02x = %x\n",
                                          address, *data);
                                status = E1000_SUCCESS;
                                break;
index 5910a932ea7c92cb67223a7c900f7c3b3e36a990..1e0c404db81a263861c2b0e683ec5b702b305df8 100644 (file)
@@ -929,11 +929,10 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw)
                         */
                        if (hw->fc.requested_mode == e1000_fc_full) {
                                hw->fc.current_mode = e1000_fc_full;
-                               hw_dbg("Flow Control = FULL.\r\n");
+                               hw_dbg("Flow Control = FULL.\n");
                        } else {
                                hw->fc.current_mode = e1000_fc_rx_pause;
-                               hw_dbg("Flow Control = "
-                                      "RX PAUSE frames only.\r\n");
+                               hw_dbg("Flow Control = RX PAUSE frames only.\n");
                        }
                }
                /* For receiving PAUSE frames ONLY.
@@ -948,7 +947,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw)
                          (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
                          (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
                        hw->fc.current_mode = e1000_fc_tx_pause;
-                       hw_dbg("Flow Control = TX PAUSE frames only.\r\n");
+                       hw_dbg("Flow Control = TX PAUSE frames only.\n");
                }
                /* For transmitting PAUSE frames ONLY.
                 *
@@ -962,7 +961,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw)
                         !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
                         (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
                        hw->fc.current_mode = e1000_fc_rx_pause;
-                       hw_dbg("Flow Control = RX PAUSE frames only.\r\n");
+                       hw_dbg("Flow Control = RX PAUSE frames only.\n");
                }
                /* Per the IEEE spec, at this point flow control should be
                 * disabled.  However, we want to consider that we could
@@ -988,10 +987,10 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw)
                         (hw->fc.requested_mode == e1000_fc_tx_pause) ||
                         (hw->fc.strict_ieee)) {
                        hw->fc.current_mode = e1000_fc_none;
-                       hw_dbg("Flow Control = NONE.\r\n");
+                       hw_dbg("Flow Control = NONE.\n");
                } else {
                        hw->fc.current_mode = e1000_fc_rx_pause;
-                       hw_dbg("Flow Control = RX PAUSE frames only.\r\n");
+                       hw_dbg("Flow Control = RX PAUSE frames only.\n");
                }
 
                /* Now we need to do one last check...  If we auto-
index fb98d4602f9d4fd130b660de0265bee786fec7a6..16430a8440fa3c5bcc299427f3052f6f2a7bdfcc 100644 (file)
@@ -5193,8 +5193,10 @@ void igb_update_stats(struct igb_adapter *adapter,
 
        rcu_read_lock();
        for (i = 0; i < adapter->num_rx_queues; i++) {
-               u32 rqdpc = rd32(E1000_RQDPC(i));
                struct igb_ring *ring = adapter->rx_ring[i];
+               u32 rqdpc = rd32(E1000_RQDPC(i));
+               if (hw->mac.type >= e1000_i210)
+                       wr32(E1000_RQDPC(i), 0);
 
                if (rqdpc) {
                        ring->rx_stats.drops += rqdpc;
index 9209d652e1c96090c712d78ce925612871ebad64..ab25e49365f79e26cfcad7a7ad12b8c5192824c9 100644 (file)
@@ -389,7 +389,7 @@ static void igb_ptp_tx_work(struct work_struct *work)
                adapter->ptp_tx_skb = NULL;
                clear_bit_unlock(__IGB_PTP_TX_IN_PROGRESS, &adapter->state);
                adapter->tx_hwtstamp_timeouts++;
-               dev_warn(&adapter->pdev->dev, "clearing Tx timestamp hang");
+               dev_warn(&adapter->pdev->dev, "clearing Tx timestamp hang\n");
                return;
        }
 
@@ -451,7 +451,7 @@ void igb_ptp_rx_hang(struct igb_adapter *adapter)
                rd32(E1000_RXSTMPH);
                adapter->last_rx_ptp_check = jiffies;
                adapter->rx_hwtstamp_cleared++;
-               dev_warn(&adapter->pdev->dev, "clearing Rx timestamp hang");
+               dev_warn(&adapter->pdev->dev, "clearing Rx timestamp hang\n");
        }
 }
 
index 1a12c1dd7a279c8f9db97c61a61ff4847c74db97..c6c4ca7d68e61a7676cd214e85f7837ee1309d39 100644 (file)
@@ -256,7 +256,6 @@ struct ixgbe_ring {
                struct ixgbe_tx_buffer *tx_buffer_info;
                struct ixgbe_rx_buffer *rx_buffer_info;
        };
-       unsigned long last_rx_timestamp;
        unsigned long state;
        u8 __iomem *tail;
        dma_addr_t dma;                 /* phys. address of descriptor ring */
@@ -770,6 +769,7 @@ struct ixgbe_adapter {
        unsigned long ptp_tx_start;
        unsigned long last_overflow_check;
        unsigned long last_rx_ptp_check;
+       unsigned long last_rx_timestamp;
        spinlock_t tmreg_lock;
        struct cyclecounter cc;
        struct timecounter tc;
@@ -944,24 +944,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter);
 void ixgbe_ptp_stop(struct ixgbe_adapter *adapter);
 void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter);
 void ixgbe_ptp_rx_hang(struct ixgbe_adapter *adapter);
-void __ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector,
-                            struct sk_buff *skb);
-static inline void ixgbe_ptp_rx_hwtstamp(struct ixgbe_ring *rx_ring,
-                                        union ixgbe_adv_rx_desc *rx_desc,
-                                        struct sk_buff *skb)
-{
-       if (unlikely(!ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_STAT_TS)))
-               return;
-
-       __ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector, skb);
-
-       /*
-        * Update the last_rx_timestamp timer in order to enable watchdog check
-        * for error case of latched timestamp on a dropped packet.
-        */
-       rx_ring->last_rx_timestamp = jiffies;
-}
-
+void ixgbe_ptp_rx_hwtstamp(struct ixgbe_adapter *adapter, struct sk_buff *skb);
 int ixgbe_ptp_set_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr);
 int ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr);
 void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter);
index 24fba39e194e682640391e42e5e618907ff230d9..981b8a7b100df5360954d056ff2c5c4d25246d73 100644 (file)
@@ -1195,7 +1195,7 @@ static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw,
         */
        hw->eeprom.word_page_size = IXGBE_EEPROM_PAGE_SIZE_MAX - data[0];
 
-       hw_dbg(hw, "Detected EEPROM page size = %d words.",
+       hw_dbg(hw, "Detected EEPROM page size = %d words.\n",
               hw->eeprom.word_page_size);
 out:
        return status;
index c4c526b7f99f48e2fe4eaccfe070273bd4078c98..d62e7a25cf972db864d6594ad1a62fd2cbe39bab 100644 (file)
@@ -1664,7 +1664,8 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring,
 
        ixgbe_rx_checksum(rx_ring, rx_desc, skb);
 
-       ixgbe_ptp_rx_hwtstamp(rx_ring, rx_desc, skb);
+       if (unlikely(ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_STAT_TS)))
+               ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector->adapter, skb);
 
        if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
            ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) {
index 23f765263f12479822654a9af55263a8db233bd7..a76af8e28a04be16386c444cc947581638f3befa 100644 (file)
@@ -536,7 +536,7 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
 
        if (time_out == max_time_out) {
                status = IXGBE_ERR_LINK_SETUP;
-               hw_dbg(hw, "ixgbe_setup_phy_link_generic: time out");
+               hw_dbg(hw, "ixgbe_setup_phy_link_generic: time out\n");
        }
 
        return status;
@@ -745,7 +745,7 @@ s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
 
        if (time_out == max_time_out) {
                status = IXGBE_ERR_LINK_SETUP;
-               hw_dbg(hw, "ixgbe_setup_phy_link_tnx: time out");
+               hw_dbg(hw, "ixgbe_setup_phy_link_tnx: time out\n");
        }
 
        return status;
@@ -1175,7 +1175,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
                                status = 0;
                        } else {
                                if (hw->allow_unsupported_sfp) {
-                                       e_warn(drv, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics.  Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter.  Intel Corporation is not responsible for any harm caused by using untested modules.");
+                                       e_warn(drv, "WARNING: Intel (R) Network Connections are quality tested using Intel (R) Ethernet Optics.  Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter.  Intel Corporation is not responsible for any harm caused by using untested modules.\n");
                                        status = 0;
                                } else {
                                        hw_dbg(hw,
index 63515a6f67fae073b40bad8c58abc55a6c238517..8902ae68345770ce5f28ba2ab91ee73bab3c7ff3 100644 (file)
@@ -435,10 +435,8 @@ void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter)
 void ixgbe_ptp_rx_hang(struct ixgbe_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
-       struct ixgbe_ring *rx_ring;
        u32 tsyncrxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL);
        unsigned long rx_event;
-       int n;
 
        /* if we don't have a valid timestamp in the registers, just update the
         * timeout counter and exit
@@ -450,18 +448,15 @@ void ixgbe_ptp_rx_hang(struct ixgbe_adapter *adapter)
 
        /* determine the most recent watchdog or rx_timestamp event */
        rx_event = adapter->last_rx_ptp_check;
-       for (n = 0; n < adapter->num_rx_queues; n++) {
-               rx_ring = adapter->rx_ring[n];
-               if (time_after(rx_ring->last_rx_timestamp, rx_event))
-                       rx_event = rx_ring->last_rx_timestamp;
-       }
+       if (time_after(adapter->last_rx_timestamp, rx_event))
+               rx_event = adapter->last_rx_timestamp;
 
        /* only need to read the high RXSTMP register to clear the lock */
        if (time_is_before_jiffies(rx_event + 5*HZ)) {
                IXGBE_READ_REG(hw, IXGBE_RXSTMPH);
                adapter->last_rx_ptp_check = jiffies;
 
-               e_warn(drv, "clearing RX Timestamp hang");
+               e_warn(drv, "clearing RX Timestamp hang\n");
        }
 }
 
@@ -517,7 +512,7 @@ static void ixgbe_ptp_tx_hwtstamp_work(struct work_struct *work)
                dev_kfree_skb_any(adapter->ptp_tx_skb);
                adapter->ptp_tx_skb = NULL;
                clear_bit_unlock(__IXGBE_PTP_TX_IN_PROGRESS, &adapter->state);
-               e_warn(drv, "clearing Tx Timestamp hang");
+               e_warn(drv, "clearing Tx Timestamp hang\n");
                return;
        }
 
@@ -530,35 +525,22 @@ static void ixgbe_ptp_tx_hwtstamp_work(struct work_struct *work)
 }
 
 /**
- * __ixgbe_ptp_rx_hwtstamp - utility function which checks for RX time stamp
- * @q_vector: structure containing interrupt and ring information
+ * ixgbe_ptp_rx_hwtstamp - utility function which checks for RX time stamp
+ * @adapter: pointer to adapter struct
  * @skb: particular skb to send timestamp with
  *
  * if the timestamp is valid, we convert it into the timecounter ns
  * value, then store that result into the shhwtstamps structure which
  * is passed up the network stack
  */
-void __ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector,
-                            struct sk_buff *skb)
+void ixgbe_ptp_rx_hwtstamp(struct ixgbe_adapter *adapter, struct sk_buff *skb)
 {
-       struct ixgbe_adapter *adapter;
-       struct ixgbe_hw *hw;
+       struct ixgbe_hw *hw = &adapter->hw;
        struct skb_shared_hwtstamps *shhwtstamps;
        u64 regval = 0, ns;
        u32 tsyncrxctl;
        unsigned long flags;
 
-       /* we cannot process timestamps on a ring without a q_vector */
-       if (!q_vector || !q_vector->adapter)
-               return;
-
-       adapter = q_vector->adapter;
-       hw = &adapter->hw;
-
-       /*
-        * Read the tsyncrxctl register afterwards in order to prevent taking an
-        * I/O hit on every packet.
-        */
        tsyncrxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL);
        if (!(tsyncrxctl & IXGBE_TSYNCRXCTL_VALID))
                return;
@@ -566,13 +548,17 @@ void __ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector,
        regval |= (u64)IXGBE_READ_REG(hw, IXGBE_RXSTMPL);
        regval |= (u64)IXGBE_READ_REG(hw, IXGBE_RXSTMPH) << 32;
 
-
        spin_lock_irqsave(&adapter->tmreg_lock, flags);
        ns = timecounter_cyc2time(&adapter->tc, regval);
        spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
 
        shhwtstamps = skb_hwtstamps(skb);
        shhwtstamps->hwtstamp = ns_to_ktime(ns);
+
+       /* Update the last_rx_timestamp timer in order to enable watchdog check
+        * for error case of latched timestamp on a dropped packet.
+        */
+       adapter->last_rx_timestamp = jiffies;
 }
 
 int ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr)
index b0c6050479eb460ae306cccaa93926f738e64c2e..b78378cea5e39b6e18627b9f39ac5249c40293fd 100644 (file)
@@ -1988,7 +1988,7 @@ jme_alloc_txdesc(struct jme_adapter *jme,
        return idx;
 }
 
-static void
+static int
 jme_fill_tx_map(struct pci_dev *pdev,
                struct txdesc *txdesc,
                struct jme_buffer_info *txbi,
@@ -2005,6 +2005,9 @@ jme_fill_tx_map(struct pci_dev *pdev,
                                len,
                                PCI_DMA_TODEVICE);
 
+       if (unlikely(pci_dma_mapping_error(pdev, dmaaddr)))
+               return -EINVAL;
+
        pci_dma_sync_single_for_device(pdev,
                                       dmaaddr,
                                       len,
@@ -2021,9 +2024,30 @@ jme_fill_tx_map(struct pci_dev *pdev,
 
        txbi->mapping = dmaaddr;
        txbi->len = len;
+       return 0;
 }
 
-static void
+static void jme_drop_tx_map(struct jme_adapter *jme, int startidx, int count)
+{
+       struct jme_ring *txring = &(jme->txring[0]);
+       struct jme_buffer_info *txbi = txring->bufinf, *ctxbi;
+       int mask = jme->tx_ring_mask;
+       int j;
+
+       for (j = 0 ; j < count ; j++) {
+               ctxbi = txbi + ((startidx + j + 2) & (mask));
+               pci_unmap_page(jme->pdev,
+                               ctxbi->mapping,
+                               ctxbi->len,
+                               PCI_DMA_TODEVICE);
+
+                               ctxbi->mapping = 0;
+                               ctxbi->len = 0;
+       }
+
+}
+
+static int
 jme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx)
 {
        struct jme_ring *txring = &(jme->txring[0]);
@@ -2034,25 +2058,37 @@ jme_map_tx_skb(struct jme_adapter *jme, struct sk_buff *skb, int idx)
        int mask = jme->tx_ring_mask;
        const struct skb_frag_struct *frag;
        u32 len;
+       int ret = 0;
 
        for (i = 0 ; i < nr_frags ; ++i) {
                frag = &skb_shinfo(skb)->frags[i];
                ctxdesc = txdesc + ((idx + i + 2) & (mask));
                ctxbi = txbi + ((idx + i + 2) & (mask));
 
-               jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi,
+               ret = jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi,
                                skb_frag_page(frag),
                                frag->page_offset, skb_frag_size(frag), hidma);
+               if (ret) {
+                       jme_drop_tx_map(jme, idx, i);
+                       goto out;
+               }
+
        }
 
        len = skb_is_nonlinear(skb) ? skb_headlen(skb) : skb->len;
        ctxdesc = txdesc + ((idx + 1) & (mask));
        ctxbi = txbi + ((idx + 1) & (mask));
-       jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, virt_to_page(skb->data),
+       ret = jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, virt_to_page(skb->data),
                        offset_in_page(skb->data), len, hidma);
+       if (ret)
+               jme_drop_tx_map(jme, idx, i);
+
+out:
+       return ret;
 
 }
 
+
 static int
 jme_tx_tso(struct sk_buff *skb, __le16 *mss, u8 *flags)
 {
@@ -2131,6 +2167,7 @@ jme_fill_tx_desc(struct jme_adapter *jme, struct sk_buff *skb, int idx)
        struct txdesc *txdesc;
        struct jme_buffer_info *txbi;
        u8 flags;
+       int ret = 0;
 
        txdesc = (struct txdesc *)txring->desc + idx;
        txbi = txring->bufinf + idx;
@@ -2155,7 +2192,10 @@ jme_fill_tx_desc(struct jme_adapter *jme, struct sk_buff *skb, int idx)
        if (jme_tx_tso(skb, &txdesc->desc1.mss, &flags))
                jme_tx_csum(jme, skb, &flags);
        jme_tx_vlan(skb, &txdesc->desc1.vlan, &flags);
-       jme_map_tx_skb(jme, skb, idx);
+       ret = jme_map_tx_skb(jme, skb, idx);
+       if (ret)
+               return ret;
+
        txdesc->desc1.flags = flags;
        /*
         * Set tx buffer info after telling NIC to send
@@ -2228,7 +2268,8 @@ jme_start_xmit(struct sk_buff *skb, struct net_device *netdev)
                return NETDEV_TX_BUSY;
        }
 
-       jme_fill_tx_desc(jme, skb, idx);
+       if (jme_fill_tx_desc(jme, skb, idx))
+               return NETDEV_TX_OK;
 
        jwrite32(jme, JME_TXCS, jme->reg_txcs |
                                TXCS_SELECT_QUEUE0 |
index b161a525fc5bd8accb44b002b64776f05d8d0319..9d5ced263a5eb3d1397e95b675a2f83e71432547 100644 (file)
@@ -232,7 +232,7 @@ static int orion_mdio_probe(struct platform_device *pdev)
                clk_prepare_enable(dev->clk);
 
        dev->err_interrupt = platform_get_irq(pdev, 0);
-       if (dev->err_interrupt != -ENXIO) {
+       if (dev->err_interrupt > 0) {
                ret = devm_request_irq(&pdev->dev, dev->err_interrupt,
                                        orion_mdio_err_irq,
                                        IRQF_SHARED, pdev->name, dev);
@@ -241,6 +241,9 @@ static int orion_mdio_probe(struct platform_device *pdev)
 
                writel(MVMDIO_ERR_INT_SMI_DONE,
                        dev->regs + MVMDIO_ERR_INT_MASK);
+
+       } else if (dev->err_interrupt == -EPROBE_DEFER) {
+               return -EPROBE_DEFER;
        }
 
        mutex_init(&dev->lock);
index 78099eab767374319c7e258bfa1f0d6df4c64fa3..92d3249f63f19a71b5ab9ed2e661cb4a8048134a 100644 (file)
@@ -1253,12 +1253,12 @@ static struct mlx4_cmd_info cmd_info[] = {
        },
        {
                .opcode = MLX4_CMD_UPDATE_QP,
-               .has_inbox = false,
+               .has_inbox = true,
                .has_outbox = false,
                .out_is_imm = false,
                .encode_slave_id = false,
                .verify = NULL,
-               .wrapper = mlx4_CMD_EPERM_wrapper
+               .wrapper = mlx4_UPDATE_QP_wrapper
        },
        {
                .opcode = MLX4_CMD_GET_OP_REQ,
index cef267e24f9c9c680613ec4ed2817c040b21c964..7cf9dadcb471bbfee9ef32761123ece4ceac131d 100644 (file)
@@ -754,10 +754,10 @@ static void mlx4_request_modules(struct mlx4_dev *dev)
                        has_eth_port = true;
        }
 
-       if (has_ib_port || (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE))
-               request_module_nowait(IB_DRV_NAME);
        if (has_eth_port)
                request_module_nowait(EN_DRV_NAME);
+       if (has_ib_port || (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE))
+               request_module_nowait(IB_DRV_NAME);
 }
 
 /*
@@ -2440,7 +2440,8 @@ slave_start:
         * No return code for this call, just warn the user in case of PCI
         * express device capabilities are under-satisfied by the bus.
         */
-       mlx4_check_pcie_caps(dev);
+       if (!mlx4_is_slave(dev))
+               mlx4_check_pcie_caps(dev);
 
        /* In master functions, the communication channel must be initialized
         * after obtaining its address from fw */
index f9c46510196341a6089b0a23d7b53455dad69ae5..212cea440f90c73424d777f94c71fe61a0c48543 100644 (file)
@@ -1195,6 +1195,12 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
                           struct mlx4_cmd_mailbox *outbox,
                           struct mlx4_cmd_info *cmd);
 
+int mlx4_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave,
+                          struct mlx4_vhcr *vhcr,
+                          struct mlx4_cmd_mailbox *inbox,
+                          struct mlx4_cmd_mailbox *outbox,
+                          struct mlx4_cmd_info *cmd);
+
 int mlx4_PROMISC_wrapper(struct mlx4_dev *dev, int slave,
                         struct mlx4_vhcr *vhcr,
                         struct mlx4_cmd_mailbox *inbox,
index cfcad26ed40f60b0e5b992195339d8c12c0e68d7..b5b3549b0c8d30e9878249c502af4d18e5162a25 100644 (file)
@@ -1106,6 +1106,9 @@ int mlx4_get_slave_from_roce_gid(struct mlx4_dev *dev, int port, u8 *gid,
        }
 
        if (found_ix >= 0) {
+               /* Calculate a slave_gid which is the slave number in the gid
+                * table and not a globally unique slave number.
+                */
                if (found_ix < MLX4_ROCE_PF_GIDS)
                        slave_gid = 0;
                else if (found_ix < MLX4_ROCE_PF_GIDS + (vf_gids % num_vfs) *
@@ -1118,41 +1121,43 @@ int mlx4_get_slave_from_roce_gid(struct mlx4_dev *dev, int port, u8 *gid,
                          ((vf_gids % num_vfs) * ((vf_gids / num_vfs + 1)))) /
                         (vf_gids / num_vfs)) + vf_gids % num_vfs + 1;
 
+               /* Calculate the globally unique slave id */
                if (slave_gid) {
                        struct mlx4_active_ports exclusive_ports;
                        struct mlx4_active_ports actv_ports;
                        struct mlx4_slaves_pport slaves_pport_actv;
                        unsigned max_port_p_one;
-                       int num_slaves_before = 1;
+                       int num_vfs_before = 0;
+                       int candidate_slave_gid;
 
+                       /* Calculate how many VFs are on the previous port, if exists */
                        for (i = 1; i < port; i++) {
                                bitmap_zero(exclusive_ports.ports, dev->caps.num_ports);
-                               set_bit(i, exclusive_ports.ports);
+                               set_bit(i - 1, exclusive_ports.ports);
                                slaves_pport_actv =
                                        mlx4_phys_to_slaves_pport_actv(
                                                        dev, &exclusive_ports);
-                               num_slaves_before += bitmap_weight(
+                               num_vfs_before += bitmap_weight(
                                                slaves_pport_actv.slaves,
                                                dev->num_vfs + 1);
                        }
 
-                       if (slave_gid < num_slaves_before) {
-                               bitmap_zero(exclusive_ports.ports, dev->caps.num_ports);
-                               set_bit(port - 1, exclusive_ports.ports);
-                               slaves_pport_actv =
-                                       mlx4_phys_to_slaves_pport_actv(
-                                                       dev, &exclusive_ports);
-                               slave_gid += bitmap_weight(
-                                               slaves_pport_actv.slaves,
-                                               dev->num_vfs + 1) -
-                                               num_slaves_before;
-                       }
-                       actv_ports = mlx4_get_active_ports(dev, slave_gid);
+                       /* candidate_slave_gid isn't necessarily the correct slave, but
+                        * it has the same number of ports and is assigned to the same
+                        * ports as the real slave we're looking for. On dual port VF,
+                        * slave_gid = [single port VFs on port <port>] +
+                        * [offset of the current slave from the first dual port VF] +
+                        * 1 (for the PF).
+                        */
+                       candidate_slave_gid = slave_gid + num_vfs_before;
+
+                       actv_ports = mlx4_get_active_ports(dev, candidate_slave_gid);
                        max_port_p_one = find_first_bit(
                                actv_ports.ports, dev->caps.num_ports) +
                                bitmap_weight(actv_ports.ports,
                                              dev->caps.num_ports) + 1;
 
+                       /* Calculate the real slave number */
                        for (i = 1; i < max_port_p_one; i++) {
                                if (i == port)
                                        continue;
index 61d64ebffd56e64b0fa8bf2d0fb69308e3d02c49..fbd32af89c7c0c2b94a36faec71f4e004048050d 100644 (file)
@@ -389,6 +389,41 @@ err_icm:
 
 EXPORT_SYMBOL_GPL(mlx4_qp_alloc);
 
+#define MLX4_UPDATE_QP_SUPPORTED_ATTRS MLX4_UPDATE_QP_SMAC
+int mlx4_update_qp(struct mlx4_dev *dev, struct mlx4_qp *qp,
+                  enum mlx4_update_qp_attr attr,
+                  struct mlx4_update_qp_params *params)
+{
+       struct mlx4_cmd_mailbox *mailbox;
+       struct mlx4_update_qp_context *cmd;
+       u64 pri_addr_path_mask = 0;
+       int err = 0;
+
+       mailbox = mlx4_alloc_cmd_mailbox(dev);
+       if (IS_ERR(mailbox))
+               return PTR_ERR(mailbox);
+
+       cmd = (struct mlx4_update_qp_context *)mailbox->buf;
+
+       if (!attr || (attr & ~MLX4_UPDATE_QP_SUPPORTED_ATTRS))
+               return -EINVAL;
+
+       if (attr & MLX4_UPDATE_QP_SMAC) {
+               pri_addr_path_mask |= 1ULL << MLX4_UPD_QP_PATH_MASK_MAC_INDEX;
+               cmd->qp_context.pri_path.grh_mylmc = params->smac_index;
+       }
+
+       cmd->primary_addr_path_mask = cpu_to_be64(pri_addr_path_mask);
+
+       err = mlx4_cmd(dev, mailbox->dma, qp->qpn & 0xffffff, 0,
+                      MLX4_CMD_UPDATE_QP, MLX4_CMD_TIME_CLASS_A,
+                      MLX4_CMD_NATIVE);
+
+       mlx4_free_cmd_mailbox(dev, mailbox);
+       return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_update_qp);
+
 void mlx4_qp_remove(struct mlx4_dev *dev, struct mlx4_qp *qp)
 {
        struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table;
index 3b5f53ef29b292d6edcb027f6b64b9c108a3a03b..8f1254a79832c24b96b227de0c30ba3ed0116520 100644 (file)
@@ -3733,6 +3733,25 @@ static int qp_detach(struct mlx4_dev *dev, struct mlx4_qp *qp,
        }
 }
 
+static int mlx4_adjust_port(struct mlx4_dev *dev, int slave,
+                           u8 *gid, enum mlx4_protocol prot)
+{
+       int real_port;
+
+       if (prot != MLX4_PROT_ETH)
+               return 0;
+
+       if (dev->caps.steering_mode == MLX4_STEERING_MODE_B0 ||
+           dev->caps.steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) {
+               real_port = mlx4_slave_convert_port(dev, slave, gid[5]);
+               if (real_port < 0)
+                       return -EINVAL;
+               gid[5] = real_port;
+       }
+
+       return 0;
+}
+
 int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
                               struct mlx4_vhcr *vhcr,
                               struct mlx4_cmd_mailbox *inbox,
@@ -3768,6 +3787,10 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
                if (err)
                        goto ex_detach;
        } else {
+               err = mlx4_adjust_port(dev, slave, gid, prot);
+               if (err)
+                       goto ex_put;
+
                err = rem_mcg_res(dev, slave, rqp, gid, prot, type, &reg_id);
                if (err)
                        goto ex_put;
@@ -3872,6 +3895,60 @@ static int add_eth_header(struct mlx4_dev *dev, int slave,
 
 }
 
+#define MLX4_UPD_QP_PATH_MASK_SUPPORTED (1ULL << MLX4_UPD_QP_PATH_MASK_MAC_INDEX)
+int mlx4_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave,
+                          struct mlx4_vhcr *vhcr,
+                          struct mlx4_cmd_mailbox *inbox,
+                          struct mlx4_cmd_mailbox *outbox,
+                          struct mlx4_cmd_info *cmd_info)
+{
+       int err;
+       u32 qpn = vhcr->in_modifier & 0xffffff;
+       struct res_qp *rqp;
+       u64 mac;
+       unsigned port;
+       u64 pri_addr_path_mask;
+       struct mlx4_update_qp_context *cmd;
+       int smac_index;
+
+       cmd = (struct mlx4_update_qp_context *)inbox->buf;
+
+       pri_addr_path_mask = be64_to_cpu(cmd->primary_addr_path_mask);
+       if (cmd->qp_mask || cmd->secondary_addr_path_mask ||
+           (pri_addr_path_mask & ~MLX4_UPD_QP_PATH_MASK_SUPPORTED))
+               return -EPERM;
+
+       /* Just change the smac for the QP */
+       err = get_res(dev, slave, qpn, RES_QP, &rqp);
+       if (err) {
+               mlx4_err(dev, "Updating qpn 0x%x for slave %d rejected\n", qpn, slave);
+               return err;
+       }
+
+       port = (rqp->sched_queue >> 6 & 1) + 1;
+       smac_index = cmd->qp_context.pri_path.grh_mylmc;
+       err = mac_find_smac_ix_in_slave(dev, slave, port,
+                                       smac_index, &mac);
+       if (err) {
+               mlx4_err(dev, "Failed to update qpn 0x%x, MAC is invalid. smac_ix: %d\n",
+                        qpn, smac_index);
+               goto err_mac;
+       }
+
+       err = mlx4_cmd(dev, inbox->dma,
+                      vhcr->in_modifier, 0,
+                      MLX4_CMD_UPDATE_QP, MLX4_CMD_TIME_CLASS_A,
+                      MLX4_CMD_NATIVE);
+       if (err) {
+               mlx4_err(dev, "Failed to update qpn on qpn 0x%x, command failed\n", qpn);
+               goto err_mac;
+       }
+
+err_mac:
+       put_res(dev, slave, qpn, RES_QP);
+       return err;
+}
+
 int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
                                         struct mlx4_vhcr *vhcr,
                                         struct mlx4_cmd_mailbox *inbox,
index 7b52a88923ef2e53fadf9aca0185e2af492aa7be..f785d01c7d123dde875a774ebf1027800af33425 100644 (file)
@@ -1719,22 +1719,6 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring)
                                tx_ring->producer;
 }
 
-static inline int qlcnic_set_real_num_queues(struct qlcnic_adapter *adapter,
-                                            struct net_device *netdev)
-{
-       int err;
-
-       netdev->num_tx_queues = adapter->drv_tx_rings;
-       netdev->real_num_tx_queues = adapter->drv_tx_rings;
-
-       err = netif_set_real_num_tx_queues(netdev, adapter->drv_tx_rings);
-       if (err)
-               netdev_err(netdev, "failed to set %d Tx queues\n",
-                          adapter->drv_tx_rings);
-
-       return err;
-}
-
 struct qlcnic_nic_template {
        int (*config_bridged_mode) (struct qlcnic_adapter *, u32);
        int (*config_led) (struct qlcnic_adapter *, u32, u32);
index dbf75393f758a153ccecfe2a8e49edb13dc8ff9a..7e55e88a81bf26ede0928225fa85998254280195 100644 (file)
@@ -2206,6 +2206,31 @@ static void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *adapter)
        ahw->max_uc_count = count;
 }
 
+static int qlcnic_set_real_num_queues(struct qlcnic_adapter *adapter,
+                                     u8 tx_queues, u8 rx_queues)
+{
+       struct net_device *netdev = adapter->netdev;
+       int err = 0;
+
+       if (tx_queues) {
+               err = netif_set_real_num_tx_queues(netdev, tx_queues);
+               if (err) {
+                       netdev_err(netdev, "failed to set %d Tx queues\n",
+                                  tx_queues);
+                       return err;
+               }
+       }
+
+       if (rx_queues) {
+               err = netif_set_real_num_rx_queues(netdev, rx_queues);
+               if (err)
+                       netdev_err(netdev, "failed to set %d Rx queues\n",
+                                  rx_queues);
+       }
+
+       return err;
+}
+
 int
 qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
                    int pci_using_dac)
@@ -2269,7 +2294,8 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
        netdev->priv_flags |= IFF_UNICAST_FLT;
        netdev->irq = adapter->msix_entries[0].vector;
 
-       err = qlcnic_set_real_num_queues(adapter, netdev);
+       err = qlcnic_set_real_num_queues(adapter, adapter->drv_tx_rings,
+                                        adapter->drv_sds_rings);
        if (err)
                return err;
 
@@ -2374,6 +2400,14 @@ void qlcnic_set_drv_version(struct qlcnic_adapter *adapter)
                qlcnic_fw_cmd_set_drv_version(adapter, fw_cmd);
 }
 
+/* Reset firmware API lock */
+static void qlcnic_reset_api_lock(struct qlcnic_adapter *adapter)
+{
+       qlcnic_api_lock(adapter);
+       qlcnic_api_unlock(adapter);
+}
+
+
 static int
 qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -2476,6 +2510,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (qlcnic_82xx_check(adapter)) {
                qlcnic_check_vf(adapter, ent);
                adapter->portnum = adapter->ahw->pci_func;
+               qlcnic_reset_api_lock(adapter);
                err = qlcnic_start_firmware(adapter);
                if (err) {
                        dev_err(&pdev->dev, "Loading fw failed.Please Reboot\n"
@@ -2934,9 +2969,13 @@ static void qlcnic_dump_tx_rings(struct qlcnic_adapter *adapter)
                            tx_ring->tx_stats.xmit_called,
                            tx_ring->tx_stats.xmit_on,
                            tx_ring->tx_stats.xmit_off);
+
+               if (tx_ring->crb_intr_mask)
+                       netdev_info(netdev, "crb_intr_mask=%d\n",
+                                   readl(tx_ring->crb_intr_mask));
+
                netdev_info(netdev,
-                           "crb_intr_mask=%d, hw_producer=%d, sw_producer=%d sw_consumer=%d, hw_consumer=%d\n",
-                           readl(tx_ring->crb_intr_mask),
+                           "hw_producer=%d, sw_producer=%d sw_consumer=%d, hw_consumer=%d\n",
                            readl(tx_ring->crb_cmd_producer),
                            tx_ring->producer, tx_ring->sw_consumer,
                            le32_to_cpu(*(tx_ring->hw_consumer)));
@@ -3969,12 +4008,21 @@ int qlcnic_validate_rings(struct qlcnic_adapter *adapter, __u32 ring_cnt,
 int qlcnic_setup_rings(struct qlcnic_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
+       u8 tx_rings, rx_rings;
        int err;
 
        if (test_bit(__QLCNIC_RESETTING, &adapter->state))
                return -EBUSY;
 
+       tx_rings = adapter->drv_tss_rings;
+       rx_rings = adapter->drv_rss_rings;
+
        netif_device_detach(netdev);
+
+       err = qlcnic_set_real_num_queues(adapter, tx_rings, rx_rings);
+       if (err)
+               goto done;
+
        if (netif_running(netdev))
                __qlcnic_down(adapter, netdev);
 
@@ -3994,7 +4042,17 @@ int qlcnic_setup_rings(struct qlcnic_adapter *adapter)
                return err;
        }
 
-       netif_set_real_num_tx_queues(netdev, adapter->drv_tx_rings);
+       /* Check if we need to update real_num_{tx|rx}_queues because
+        * qlcnic_setup_intr() may change Tx/Rx rings size
+        */
+       if ((tx_rings != adapter->drv_tx_rings) ||
+           (rx_rings != adapter->drv_sds_rings)) {
+               err = qlcnic_set_real_num_queues(adapter,
+                                                adapter->drv_tx_rings,
+                                                adapter->drv_sds_rings);
+               if (err)
+                       goto done;
+       }
 
        if (qlcnic_83xx_check(adapter)) {
                qlcnic_83xx_initialize_nic(adapter, 1);
index 0638c1810d54547df9eafb961439085dff4364a2..6afe9c1f5ab9337a3fa7c64e7863664af3db99b7 100644 (file)
@@ -1370,7 +1370,7 @@ static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter,
 
        rsp = qlcnic_sriov_alloc_bc_trans(&trans);
        if (rsp)
-               return rsp;
+               goto free_cmd;
 
        rsp = qlcnic_sriov_prepare_bc_hdr(trans, cmd, seq, QLC_BC_COMMAND);
        if (rsp)
@@ -1425,6 +1425,13 @@ err_out:
 
 cleanup_transaction:
        qlcnic_sriov_cleanup_transaction(trans);
+
+free_cmd:
+       if (cmd->type == QLC_83XX_MBX_CMD_NO_WAIT) {
+               qlcnic_free_mbx_args(cmd);
+               kfree(cmd);
+       }
+
        return rsp;
 }
 
index 6203c7d8550fda4a530ec91e0a089870e507b4cb..45019649bbbd73227840d866ed92709e22a0d49c 100644 (file)
@@ -358,6 +358,8 @@ struct sxgbe_core_ops {
        /* Enable disable checksum offload operations */
        void (*enable_rx_csum)(void __iomem *ioaddr);
        void (*disable_rx_csum)(void __iomem *ioaddr);
+       void (*enable_rxqueue)(void __iomem *ioaddr, int queue_num);
+       void (*disable_rxqueue)(void __iomem *ioaddr, int queue_num);
 };
 
 const struct sxgbe_core_ops *sxgbe_get_core_ops(void);
index c4da7a2b002a16fa432f0bbe6fbce25be9085acc..58c35692560e599f0977c6460edcd0a616889e5f 100644 (file)
@@ -165,6 +165,26 @@ static void sxgbe_core_set_speed(void __iomem *ioaddr, unsigned char speed)
        writel(tx_cfg, ioaddr + SXGBE_CORE_TX_CONFIG_REG);
 }
 
+static void sxgbe_core_enable_rxqueue(void __iomem *ioaddr, int queue_num)
+{
+       u32 reg_val;
+
+       reg_val = readl(ioaddr + SXGBE_CORE_RX_CTL0_REG);
+       reg_val &= ~(SXGBE_CORE_RXQ_ENABLE_MASK << queue_num);
+       reg_val |= SXGBE_CORE_RXQ_ENABLE;
+       writel(reg_val, ioaddr + SXGBE_CORE_RX_CTL0_REG);
+}
+
+static void sxgbe_core_disable_rxqueue(void __iomem *ioaddr, int queue_num)
+{
+       u32 reg_val;
+
+       reg_val = readl(ioaddr + SXGBE_CORE_RX_CTL0_REG);
+       reg_val &= ~(SXGBE_CORE_RXQ_ENABLE_MASK << queue_num);
+       reg_val |= SXGBE_CORE_RXQ_DISABLE;
+       writel(reg_val, ioaddr + SXGBE_CORE_RX_CTL0_REG);
+}
+
 static void  sxgbe_set_eee_mode(void __iomem *ioaddr)
 {
        u32 ctrl;
@@ -254,6 +274,8 @@ static const struct sxgbe_core_ops core_ops = {
        .set_eee_pls            = sxgbe_set_eee_pls,
        .enable_rx_csum         = sxgbe_enable_rx_csum,
        .disable_rx_csum        = sxgbe_disable_rx_csum,
+       .enable_rxqueue         = sxgbe_core_enable_rxqueue,
+       .disable_rxqueue        = sxgbe_core_disable_rxqueue,
 };
 
 const struct sxgbe_core_ops *sxgbe_get_core_ops(void)
index e896dbbd2e156514eaf1d83ed8e132fbc3d88e37..2686bb5b6765680a8e18eeabd89146384da1c6f5 100644 (file)
@@ -45,10 +45,10 @@ static void sxgbe_prepare_tx_desc(struct sxgbe_tx_norm_desc *p, u8 is_fd,
        p->tdes23.tx_rd_des23.first_desc = is_fd;
        p->tdes23.tx_rd_des23.buf1_size = buf1_len;
 
-       p->tdes23.tx_rd_des23.tx_pkt_len.cksum_pktlen.total_pkt_len = pkt_len;
+       p->tdes23.tx_rd_des23.tx_pkt_len.pkt_len.total_pkt_len = pkt_len;
 
        if (cksum)
-               p->tdes23.tx_rd_des23.tx_pkt_len.cksum_pktlen.cksum_ctl = cic_full;
+               p->tdes23.tx_rd_des23.cksum_ctl = cic_full;
 }
 
 /* Set VLAN control information */
@@ -233,6 +233,12 @@ static void sxgbe_set_rx_owner(struct sxgbe_rx_norm_desc *p)
        p->rdes23.rx_rd_des23.own_bit = 1;
 }
 
+/* Set Interrupt on completion bit */
+static void sxgbe_set_rx_int_on_com(struct sxgbe_rx_norm_desc *p)
+{
+       p->rdes23.rx_rd_des23.int_on_com = 1;
+}
+
 /* Get the receive frame size */
 static int sxgbe_get_rx_frame_len(struct sxgbe_rx_norm_desc *p)
 {
@@ -498,6 +504,7 @@ static const struct sxgbe_desc_ops desc_ops = {
        .init_rx_desc                   = sxgbe_init_rx_desc,
        .get_rx_owner                   = sxgbe_get_rx_owner,
        .set_rx_owner                   = sxgbe_set_rx_owner,
+       .set_rx_int_on_com              = sxgbe_set_rx_int_on_com,
        .get_rx_frame_len               = sxgbe_get_rx_frame_len,
        .get_rx_fd_status               = sxgbe_get_rx_fd_status,
        .get_rx_ld_status               = sxgbe_get_rx_ld_status,
index 838cb9fb0ea979514bafc7b068cd4c09f3ee5d49..18609324db723dc2fbf5c50880d876ba83deb3d3 100644 (file)
@@ -39,22 +39,22 @@ struct sxgbe_tx_norm_desc {
                        u32 int_on_com:1;
                        /* TDES3 */
                        union {
-                               u32 tcp_payload_len:18;
+                               u16 tcp_payload_len;
                                struct {
                                        u32 total_pkt_len:15;
                                        u32 reserved1:1;
-                                       u32 cksum_ctl:2;
-                               } cksum_pktlen;
+                               } pkt_len;
                        } tx_pkt_len;
 
-                       u32 tse_bit:1;
-                       u32 tcp_hdr_len:4;
-                       u32 sa_insert_ctl:3;
-                       u32 crc_pad_ctl:2;
-                       u32 last_desc:1;
-                       u32 first_desc:1;
-                       u32 ctxt_bit:1;
-                       u32 own_bit:1;
+                       u16 cksum_ctl:2;
+                       u16 tse_bit:1;
+                       u16 tcp_hdr_len:4;
+                       u16 sa_insert_ctl:3;
+                       u16 crc_pad_ctl:2;
+                       u16 last_desc:1;
+                       u16 first_desc:1;
+                       u16 ctxt_bit:1;
+                       u16 own_bit:1;
                } tx_rd_des23;
 
                /* tx write back Desc 2,3 */
@@ -70,25 +70,20 @@ struct sxgbe_tx_norm_desc {
 
 struct sxgbe_rx_norm_desc {
        union {
-               u32 rdes0; /* buf1 address */
-               struct {
+               u64 rdes01; /* buf1 address */
+               union {
                        u32 out_vlan_tag:16;
                        u32 in_vlan_tag:16;
-               } wb_rx_des0;
-       } rd_wb_des0;
-
-       union {
-               u32 rdes1;      /* buf2 address or buf1[63:32] */
-               u32 rss_hash;   /* Write-back RX */
-       } rd_wb_des1;
+                       u32 rss_hash;
+               } rx_wb_des01;
+       } rdes01;
 
        union {
                /* RX Read format Desc 2,3 */
                struct{
                        /* RDES2 */
-                       u32 buf2_addr;
+                       u64 buf2_addr:62;
                        /* RDES3 */
-                       u32 buf2_hi_addr:30;
                        u32 int_on_com:1;
                        u32 own_bit:1;
                } rx_rd_des23;
@@ -263,6 +258,9 @@ struct sxgbe_desc_ops {
        /* Set own bit */
        void (*set_rx_owner)(struct sxgbe_rx_norm_desc *p);
 
+       /* Set Interrupt on completion bit */
+       void (*set_rx_int_on_com)(struct sxgbe_rx_norm_desc *p);
+
        /* Get the receive frame size */
        int (*get_rx_frame_len)(struct sxgbe_rx_norm_desc *p);
 
index 4d989ff6c978a8ad67d36afbb7d2df5ef6632929..bb9b5b8afc5f4417bae05c4ef0e1ea02f84b7421 100644 (file)
 /* DMA core initialization */
 static int sxgbe_dma_init(void __iomem *ioaddr, int fix_burst, int burst_map)
 {
-       int retry_count = 10;
        u32 reg_val;
 
-       /* reset the DMA */
-       writel(SXGBE_DMA_SOFT_RESET, ioaddr + SXGBE_DMA_MODE_REG);
-       while (retry_count--) {
-               if (!(readl(ioaddr + SXGBE_DMA_MODE_REG) &
-                     SXGBE_DMA_SOFT_RESET))
-                       break;
-               mdelay(10);
-       }
-
-       if (retry_count < 0)
-               return -EBUSY;
-
        reg_val = readl(ioaddr + SXGBE_DMA_SYSBUS_MODE_REG);
 
        /* if fix_burst = 0, Set UNDEF = 1 of DMA_Sys_Mode Register.
index 27e8c824b204fc8ec16c0f927216676415ca5834..82a9a983869fe6ae711c5b4503941611f1f32657 100644 (file)
@@ -1076,6 +1076,9 @@ static int sxgbe_open(struct net_device *dev)
 
        /* Initialize the MAC Core */
        priv->hw->mac->core_init(priv->ioaddr);
+       SXGBE_FOR_EACH_QUEUE(SXGBE_RX_QUEUES, queue_num) {
+               priv->hw->mac->enable_rxqueue(priv->ioaddr, queue_num);
+       }
 
        /* Request the IRQ lines */
        ret = devm_request_irq(priv->device, priv->irq, sxgbe_common_interrupt,
@@ -1453,6 +1456,7 @@ static void sxgbe_rx_refill(struct sxgbe_priv_data *priv)
                /* Added memory barrier for RX descriptor modification */
                wmb();
                priv->hw->desc->set_rx_owner(p);
+               priv->hw->desc->set_rx_int_on_com(p);
                /* Added memory barrier for RX descriptor modification */
                wmb();
        }
@@ -2070,6 +2074,24 @@ static int sxgbe_hw_init(struct sxgbe_priv_data * const priv)
        return 0;
 }
 
+static int sxgbe_sw_reset(void __iomem *addr)
+{
+       int retry_count = 10;
+
+       writel(SXGBE_DMA_SOFT_RESET, addr + SXGBE_DMA_MODE_REG);
+       while (retry_count--) {
+               if (!(readl(addr + SXGBE_DMA_MODE_REG) &
+                     SXGBE_DMA_SOFT_RESET))
+                       break;
+               mdelay(10);
+       }
+
+       if (retry_count < 0)
+               return -EBUSY;
+
+       return 0;
+}
+
 /**
  * sxgbe_drv_probe
  * @device: device pointer
@@ -2102,6 +2124,10 @@ struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device,
        priv->plat = plat_dat;
        priv->ioaddr = addr;
 
+       ret = sxgbe_sw_reset(priv->ioaddr);
+       if (ret)
+               goto error_free_netdev;
+
        /* Verify driver arguments */
        sxgbe_verify_args();
 
@@ -2218,9 +2244,14 @@ error_free_netdev:
 int sxgbe_drv_remove(struct net_device *ndev)
 {
        struct sxgbe_priv_data *priv = netdev_priv(ndev);
+       u8 queue_num;
 
        netdev_info(ndev, "%s: removing driver\n", __func__);
 
+       SXGBE_FOR_EACH_QUEUE(SXGBE_RX_QUEUES, queue_num) {
+               priv->hw->mac->disable_rxqueue(priv->ioaddr, queue_num);
+       }
+
        priv->hw->dma->stop_rx(priv->ioaddr, SXGBE_RX_QUEUES);
        priv->hw->dma->stop_tx(priv->ioaddr, SXGBE_TX_QUEUES);
 
index 01af2cbb479d10a96c1038bfc3f2ff167a20beb3..43ccb4a6de15a3fe2dedc9198a3866fd89143f47 100644 (file)
@@ -27,7 +27,7 @@
 #define SXGBE_SMA_PREAD_CMD    0x02 /* post read  increament address */
 #define SXGBE_SMA_READ_CMD     0x03 /* read command */
 #define SXGBE_SMA_SKIP_ADDRFRM 0x00040000 /* skip the address frame */
-#define SXGBE_MII_BUSY         0x00800000 /* mii busy */
+#define SXGBE_MII_BUSY         0x00400000 /* mii busy */
 
 static int sxgbe_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_data)
 {
@@ -147,6 +147,7 @@ int sxgbe_mdio_register(struct net_device *ndev)
        struct sxgbe_mdio_bus_data *mdio_data = priv->plat->mdio_bus_data;
        int err, phy_addr;
        int *irqlist;
+       bool phy_found = false;
        bool act;
 
        /* allocate the new mdio bus */
@@ -162,7 +163,7 @@ int sxgbe_mdio_register(struct net_device *ndev)
                irqlist = priv->mii_irq;
 
        /* assign mii bus fields */
-       mdio_bus->name = "samsxgbe";
+       mdio_bus->name = "sxgbe";
        mdio_bus->read = &sxgbe_mdio_read;
        mdio_bus->write = &sxgbe_mdio_write;
        snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%x",
@@ -216,13 +217,22 @@ int sxgbe_mdio_register(struct net_device *ndev)
                        netdev_info(ndev, "PHY ID %08x at %d IRQ %s (%s)%s\n",
                                    phy->phy_id, phy_addr, irq_str,
                                    dev_name(&phy->dev), act ? " active" : "");
+                       phy_found = true;
                }
        }
 
+       if (!phy_found) {
+               netdev_err(ndev, "PHY not found\n");
+               goto phyfound_err;
+       }
+
        priv->mii = mdio_bus;
 
        return 0;
 
+phyfound_err:
+       err = -ENODEV;
+       mdiobus_unregister(mdio_bus);
 mdiobus_err:
        mdiobus_free(mdio_bus);
        return err;
index 5a89acb4c505fc83f3847a10c437c961db079dec..56f8bf5a3f1b99564a2b055830810fe3d156e6c4 100644 (file)
 #define SXGBE_CORE_RX_CTL2_REG         0x00A8
 #define SXGBE_CORE_RX_CTL3_REG         0x00AC
 
+#define SXGBE_CORE_RXQ_ENABLE_MASK     0x0003
+#define SXGBE_CORE_RXQ_ENABLE          0x0002
+#define SXGBE_CORE_RXQ_DISABLE         0x0000
+
 /* Interrupt Registers */
 #define SXGBE_CORE_INT_STATUS_REG      0x00B0
 #define SXGBE_CORE_INT_ENABLE_REG      0x00B4
index 32d969e857f7befc79bf4a6f18cb153c350b374b..89b83e59e1dc601898ddd60bd0fa704fdd7b6d43 100644 (file)
@@ -156,13 +156,15 @@ void efx_nic_fini_interrupt(struct efx_nic *efx)
        efx->net_dev->rx_cpu_rmap = NULL;
 #endif
 
-       /* Disable MSI/MSI-X interrupts */
-       efx_for_each_channel(channel, efx)
-               free_irq(channel->irq, &efx->msi_context[channel->channel]);
-
-       /* Disable legacy interrupt */
-       if (efx->legacy_irq)
+       if (EFX_INT_MODE_USE_MSI(efx)) {
+               /* Disable MSI/MSI-X interrupts */
+               efx_for_each_channel(channel, efx)
+                       free_irq(channel->irq,
+                                &efx->msi_context[channel->channel]);
+       } else {
+               /* Disable legacy interrupt */
                free_irq(efx->legacy_irq, efx);
+       }
 }
 
 /* Register dump */
index d1b4dca53a9d10be97f05e2e09dd08418598bf05..bcaa41af1e628e9f8d2e84fccc7a38ea716e428c 100644 (file)
@@ -147,18 +147,19 @@ MODULE_ALIAS("platform:smc91x");
  */
 #define MII_DELAY              1
 
-#if SMC_DEBUG > 0
-#define DBG(n, dev, args...)                           \
-       do {                                            \
-               if (SMC_DEBUG >= (n))                   \
-                       netdev_dbg(dev, args);          \
+#define DBG(n, dev, fmt, ...)                                  \
+       do {                                                    \
+               if (SMC_DEBUG >= (n))                           \
+                       netdev_dbg(dev, fmt, ##__VA_ARGS__);    \
        } while (0)
 
-#define PRINTK(dev, args...)   netdev_info(dev, args)
-#else
-#define DBG(n, dev, args...)   do { } while (0)
-#define PRINTK(dev, args...)   netdev_dbg(dev, args)
-#endif
+#define PRINTK(dev, fmt, ...)                                  \
+       do {                                                    \
+               if (SMC_DEBUG > 0)                              \
+                       netdev_info(dev, fmt, ##__VA_ARGS__);   \
+               else                                            \
+                       netdev_dbg(dev, fmt, ##__VA_ARGS__);    \
+       } while (0)
 
 #if SMC_DEBUG > 3
 static void PRINT_PKT(u_char *buf, int length)
@@ -191,7 +192,7 @@ static void PRINT_PKT(u_char *buf, int length)
        pr_cont("\n");
 }
 #else
-#define PRINT_PKT(x...)  do { } while (0)
+static inline void PRINT_PKT(u_char *buf, int length) { }
 #endif
 
 
@@ -1781,7 +1782,7 @@ static int smc_findirq(struct smc_local *lp)
        int timeout = 20;
        unsigned long cookie;
 
-       DBG(2, dev, "%s: %s\n", CARDNAME, __func__);
+       DBG(2, lp->dev, "%s: %s\n", CARDNAME, __func__);
 
        cookie = probe_irq_on();
 
index d940034acdd4aa465153f80ae0d5881cb648d6a8..0f4841d2e8dc9b556bde072a1786697ea7041460 100644 (file)
@@ -1704,7 +1704,7 @@ static int stmmac_open(struct net_device *dev)
                if (ret) {
                        pr_err("%s: Cannot attach to PHY (error: %d)\n",
                               __func__, ret);
-                       goto phy_error;
+                       return ret;
                }
        }
 
@@ -1779,8 +1779,6 @@ init_error:
 dma_desc_error:
        if (priv->phydev)
                phy_disconnect(priv->phydev);
-phy_error:
-       clk_disable_unprepare(priv->stmmac_clk);
 
        return ret;
 }
index df8d383acf48ed0da087bb19d144499484ac0376..b9ac20f42651bd90e33e5fcb3da38db5401117a2 100644 (file)
@@ -246,7 +246,7 @@ static inline void cas_lock_tx(struct cas *cp)
        int i;
 
        for (i = 0; i < N_TX_RINGS; i++)
-               spin_lock(&cp->tx_lock[i]);
+               spin_lock_nested(&cp->tx_lock[i], i);
 }
 
 static inline void cas_lock_all(struct cas *cp)
index 36aa109416c4c3a387a440795a8d3611cf3d4ded..c331b7ebc8124585f989d6fb3dcdbaf8a3d7d3ed 100644 (file)
@@ -1871,18 +1871,13 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                mdio_node = of_find_node_by_phandle(be32_to_cpup(parp));
                phyid = be32_to_cpup(parp+1);
                mdio = of_find_device_by_node(mdio_node);
-
-               if (strncmp(mdio->name, "gpio", 4) == 0) {
-                       /* GPIO bitbang MDIO driver attached */
-                       struct mii_bus *bus = dev_get_drvdata(&mdio->dev);
-
-                       snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
-                                PHY_ID_FMT, bus->id, phyid);
-               } else {
-                       /* davinci MDIO driver attached */
-                       snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
-                                PHY_ID_FMT, mdio->name, phyid);
+               of_node_put(mdio_node);
+               if (!mdio) {
+                       pr_err("Missing mdio platform device\n");
+                       return -EINVAL;
                }
+               snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
+                        PHY_ID_FMT, mdio->name, phyid);
 
                mac_addr = of_get_mac_address(slave_node);
                if (mac_addr)
index 31e55fba7cadd03d9e19221139727272b9eeec77..7918d5132c1f14764cda43daf9f98d7f7c01f310 100644 (file)
@@ -382,6 +382,10 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
        if (skb_is_gso(skb))
                goto do_lso;
 
+       if ((skb->ip_summed == CHECKSUM_NONE) ||
+           (skb->ip_summed == CHECKSUM_UNNECESSARY))
+               goto do_send;
+
        rndis_msg_size += NDIS_CSUM_PPI_SIZE;
        ppi = init_ppi_data(rndis_msg, NDIS_CSUM_PPI_SIZE,
                            TCPIP_CHKSUM_PKTINFO);
index 753a8c23d15d9af1e138ec6fda410aeda32d288b..d53e299ae1d97ca39c4f3af511b97c5dacb32827 100644 (file)
@@ -263,11 +263,9 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
        const struct macvlan_dev *vlan = netdev_priv(dev);
        const struct macvlan_port *port = vlan->port;
        const struct macvlan_dev *dest;
-       __u8 ip_summed = skb->ip_summed;
 
        if (vlan->mode == MACVLAN_MODE_BRIDGE) {
                const struct ethhdr *eth = (void *)skb->data;
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
 
                /* send to other bridge ports directly */
                if (is_multicast_ether_addr(eth->h_dest)) {
@@ -285,7 +283,6 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
 xmit_world:
-       skb->ip_summed = ip_summed;
        skb->dev = vlan->lowerdev;
        return dev_queue_xmit(skb);
 }
@@ -461,8 +458,10 @@ static void macvlan_change_rx_flags(struct net_device *dev, int change)
        struct macvlan_dev *vlan = netdev_priv(dev);
        struct net_device *lowerdev = vlan->lowerdev;
 
-       if (change & IFF_ALLMULTI)
-               dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1);
+       if (dev->flags & IFF_UP) {
+               if (change & IFF_ALLMULTI)
+                       dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1);
+       }
 }
 
 static void macvlan_set_mac_lists(struct net_device *dev)
@@ -518,6 +517,11 @@ static struct lock_class_key macvlan_netdev_addr_lock_key;
 #define MACVLAN_STATE_MASK \
        ((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))
 
+static int macvlan_get_nest_level(struct net_device *dev)
+{
+       return ((struct macvlan_dev *)netdev_priv(dev))->nest_level;
+}
+
 static void macvlan_set_lockdep_class_one(struct net_device *dev,
                                          struct netdev_queue *txq,
                                          void *_unused)
@@ -528,8 +532,9 @@ static void macvlan_set_lockdep_class_one(struct net_device *dev,
 
 static void macvlan_set_lockdep_class(struct net_device *dev)
 {
-       lockdep_set_class(&dev->addr_list_lock,
-                         &macvlan_netdev_addr_lock_key);
+       lockdep_set_class_and_subclass(&dev->addr_list_lock,
+                                      &macvlan_netdev_addr_lock_key,
+                                      macvlan_get_nest_level(dev));
        netdev_for_each_tx_queue(dev, macvlan_set_lockdep_class_one, NULL);
 }
 
@@ -724,6 +729,7 @@ static const struct net_device_ops macvlan_netdev_ops = {
        .ndo_fdb_add            = macvlan_fdb_add,
        .ndo_fdb_del            = macvlan_fdb_del,
        .ndo_fdb_dump           = ndo_dflt_fdb_dump,
+       .ndo_get_lock_subclass  = macvlan_get_nest_level,
 };
 
 void macvlan_common_setup(struct net_device *dev)
@@ -852,6 +858,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
        vlan->dev      = dev;
        vlan->port     = port;
        vlan->set_features = MACVLAN_FEATURES;
+       vlan->nest_level = dev_get_nest_level(lowerdev, netif_is_macvlan) + 1;
 
        vlan->mode     = MACVLAN_MODE_VEPA;
        if (data && data[IFLA_MACVLAN_MODE])
index ff111a89e17f9c66561d79916d8d57e282c119d2..3381c4f91a8cc236df0df8be59bd586538480498 100644 (file)
@@ -322,6 +322,15 @@ static rx_handler_result_t macvtap_handle_frame(struct sk_buff **pskb)
                        segs = nskb;
                }
        } else {
+               /* If we receive a partial checksum and the tap side
+                * doesn't support checksum offload, compute the checksum.
+                * Note: it doesn't matter which checksum feature to
+                *        check, we either support them all or none.
+                */
+               if (skb->ip_summed == CHECKSUM_PARTIAL &&
+                   !(features & NETIF_F_ALL_CSUM) &&
+                   skb_checksum_help(skb))
+                       goto drop;
                skb_queue_tail(&q->sk.sk_receive_queue, skb);
        }
 
index 9c4defdec67b09299f38f1b06bf8eacbccd007d1..5f1a2250018fec5ba01a2a1a1a11f2d736f544a9 100644 (file)
@@ -215,6 +215,10 @@ static int mdio_gpio_probe(struct platform_device *pdev)
        if (pdev->dev.of_node) {
                pdata = mdio_gpio_of_get_data(pdev);
                bus_id = of_alias_get_id(pdev->dev.of_node, "mdio-gpio");
+               if (bus_id < 0) {
+                       dev_warn(&pdev->dev, "failed to get alias id\n");
+                       bus_id = 0;
+               }
        } else {
                pdata = dev_get_platdata(&pdev->dev);
                bus_id = pdev->id;
index 5ad971a55c5d9f21ffb3ded8e9d5704534095d21..d849684231c14919727cb66d5e6e37b14278943d 100644 (file)
@@ -246,13 +246,13 @@ static int ksz9021_load_values_from_of(struct phy_device *phydev,
        if (val1 != -1)
                newval = ((newval & 0xfff0) | ((val1 / PS_TO_REG) & 0xf) << 0);
 
-       if (val2 != -1)
+       if (val2 != -2)
                newval = ((newval & 0xff0f) | ((val2 / PS_TO_REG) & 0xf) << 4);
 
-       if (val3 != -1)
+       if (val3 != -3)
                newval = ((newval & 0xf0ff) | ((val3 / PS_TO_REG) & 0xf) << 8);
 
-       if (val4 != -1)
+       if (val4 != -4)
                newval = ((newval & 0x0fff) | ((val4 / PS_TO_REG) & 0xf) << 12);
 
        return kszphy_extended_write(phydev, reg, newval);
index 1b6d09aef42748bcbba6d4fe88ca68d6ea83c852..3bc079a67a3dc85a222e2b784f7f65ec55dc6b59 100644 (file)
@@ -715,7 +715,7 @@ void phy_state_machine(struct work_struct *work)
        struct delayed_work *dwork = to_delayed_work(work);
        struct phy_device *phydev =
                        container_of(dwork, struct phy_device, state_queue);
-       int needs_aneg = 0, do_suspend = 0;
+       bool needs_aneg = false, do_suspend = false, do_resume = false;
        int err = 0;
 
        mutex_lock(&phydev->lock);
@@ -727,7 +727,7 @@ void phy_state_machine(struct work_struct *work)
        case PHY_PENDING:
                break;
        case PHY_UP:
-               needs_aneg = 1;
+               needs_aneg = true;
 
                phydev->link_timeout = PHY_AN_TIMEOUT;
 
@@ -757,7 +757,7 @@ void phy_state_machine(struct work_struct *work)
                        phydev->adjust_link(phydev->attached_dev);
 
                } else if (0 == phydev->link_timeout--)
-                       needs_aneg = 1;
+                       needs_aneg = true;
                break;
        case PHY_NOLINK:
                err = phy_read_status(phydev);
@@ -765,6 +765,17 @@ void phy_state_machine(struct work_struct *work)
                        break;
 
                if (phydev->link) {
+                       if (AUTONEG_ENABLE == phydev->autoneg) {
+                               err = phy_aneg_done(phydev);
+                               if (err < 0)
+                                       break;
+
+                               if (!err) {
+                                       phydev->state = PHY_AN;
+                                       phydev->link_timeout = PHY_AN_TIMEOUT;
+                                       break;
+                               }
+                       }
                        phydev->state = PHY_RUNNING;
                        netif_carrier_on(phydev->attached_dev);
                        phydev->adjust_link(phydev->attached_dev);
@@ -780,7 +791,7 @@ void phy_state_machine(struct work_struct *work)
                        netif_carrier_on(phydev->attached_dev);
                } else {
                        if (0 == phydev->link_timeout--)
-                               needs_aneg = 1;
+                               needs_aneg = true;
                }
 
                phydev->adjust_link(phydev->attached_dev);
@@ -816,7 +827,7 @@ void phy_state_machine(struct work_struct *work)
                        phydev->link = 0;
                        netif_carrier_off(phydev->attached_dev);
                        phydev->adjust_link(phydev->attached_dev);
-                       do_suspend = 1;
+                       do_suspend = true;
                }
                break;
        case PHY_RESUMING:
@@ -865,6 +876,7 @@ void phy_state_machine(struct work_struct *work)
                        }
                        phydev->adjust_link(phydev->attached_dev);
                }
+               do_resume = true;
                break;
        }
 
@@ -872,9 +884,10 @@ void phy_state_machine(struct work_struct *work)
 
        if (needs_aneg)
                err = phy_start_aneg(phydev);
-
-       if (do_suspend)
+       else if (do_suspend)
                phy_suspend(phydev);
+       else if (do_resume)
+               phy_resume(phydev);
 
        if (err < 0)
                phy_error(phydev);
index 0ce606624296a80492b18d89a27634614aad5497..4987a1c6dc52e63220edb6fc94eea925a9fdf122 100644 (file)
@@ -614,8 +614,8 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
        err = phy_init_hw(phydev);
        if (err)
                phy_detach(phydev);
-
-       phy_resume(phydev);
+       else
+               phy_resume(phydev);
 
        return err;
 }
index cc70ecfc70626789183e462c8b51d13f0c7fc8aa..ad4a94e9ff57c77574820fe3e188b12986feff55 100644 (file)
@@ -429,13 +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);
+       spin_lock_bh(&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);
+               spin_unlock_bh(&sl->lock);
                sl_unlock(sl);
                return;
        }
@@ -443,7 +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);
+       spin_unlock_bh(&sl->lock);
 }
 
 static void sl_tx_timeout(struct net_device *dev)
index 33008c1d1d678756ae8fbae13238763c24cc603e..767fe61b5ac995323fa4d3e2d1b2d7ac3869ec00 100644 (file)
@@ -2834,8 +2834,10 @@ static int team_device_event(struct notifier_block *unused,
        case NETDEV_UP:
                if (netif_carrier_ok(dev))
                        team_port_change_check(port, true);
+               break;
        case NETDEV_DOWN:
                team_port_change_check(port, false);
+               break;
        case NETDEV_CHANGE:
                if (netif_running(port->dev))
                        team_port_change_check(port,
index c9f3281506af568e534a47789418b466a0a77adc..2e025ddcef210bc888dd8a8ff81473a32c3dd154 100644 (file)
@@ -120,6 +120,16 @@ static void cdc_mbim_unbind(struct usbnet *dev, struct usb_interface *intf)
        cdc_ncm_unbind(dev, intf);
 }
 
+/* verify that the ethernet protocol is IPv4 or IPv6 */
+static bool is_ip_proto(__be16 proto)
+{
+       switch (proto) {
+       case htons(ETH_P_IP):
+       case htons(ETH_P_IPV6):
+               return true;
+       }
+       return false;
+}
 
 static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
 {
@@ -128,6 +138,7 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb
        struct cdc_ncm_ctx *ctx = info->ctx;
        __le32 sign = cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN);
        u16 tci = 0;
+       bool is_ip;
        u8 *c;
 
        if (!ctx)
@@ -137,25 +148,32 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb
                if (skb->len <= ETH_HLEN)
                        goto error;
 
+               /* Some applications using e.g. packet sockets will
+                * bypass the VLAN acceleration and create tagged
+                * ethernet frames directly.  We primarily look for
+                * the accelerated out-of-band tag, but fall back if
+                * required
+                */
+               skb_reset_mac_header(skb);
+               if (vlan_get_tag(skb, &tci) < 0 && skb->len > VLAN_ETH_HLEN &&
+                   __vlan_get_tag(skb, &tci) == 0) {
+                       is_ip = is_ip_proto(vlan_eth_hdr(skb)->h_vlan_encapsulated_proto);
+                       skb_pull(skb, VLAN_ETH_HLEN);
+               } else {
+                       is_ip = is_ip_proto(eth_hdr(skb)->h_proto);
+                       skb_pull(skb, ETH_HLEN);
+               }
+
                /* mapping VLANs to MBIM sessions:
                 *   no tag     => IPS session <0>
                 *   1 - 255    => IPS session <vlanid>
                 *   256 - 511  => DSS session <vlanid - 256>
                 *   512 - 4095 => unsupported, drop
                 */
-               vlan_get_tag(skb, &tci);
-
                switch (tci & 0x0f00) {
                case 0x0000: /* VLAN ID 0 - 255 */
-                       /* verify that datagram is IPv4 or IPv6 */
-                       skb_reset_mac_header(skb);
-                       switch (eth_hdr(skb)->h_proto) {
-                       case htons(ETH_P_IP):
-                       case htons(ETH_P_IPV6):
-                               break;
-                       default:
+                       if (!is_ip)
                                goto error;
-                       }
                        c = (u8 *)&sign;
                        c[3] = tci;
                        break;
@@ -169,7 +187,6 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb
                                  "unsupported tci=0x%04x\n", tci);
                        goto error;
                }
-               skb_pull(skb, ETH_HLEN);
        }
 
        spin_lock_bh(&ctx->mtx);
@@ -204,17 +221,23 @@ static void do_neigh_solicit(struct usbnet *dev, u8 *buf, u16 tci)
                return;
 
        /* need to send the NA on the VLAN dev, if any */
-       if (tci)
+       rcu_read_lock();
+       if (tci) {
                netdev = __vlan_find_dev_deep(dev->net, htons(ETH_P_8021Q),
                                              tci);
-       else
+               if (!netdev) {
+                       rcu_read_unlock();
+                       return;
+               }
+       } else {
                netdev = dev->net;
-       if (!netdev)
-               return;
+       }
+       dev_hold(netdev);
+       rcu_read_unlock();
 
        in6_dev = in6_dev_get(netdev);
        if (!in6_dev)
-               return;
+               goto out;
        is_router = !!in6_dev->cnf.forwarding;
        in6_dev_put(in6_dev);
 
@@ -224,6 +247,8 @@ static void do_neigh_solicit(struct usbnet *dev, u8 *buf, u16 tci)
                                 true /* solicited */,
                                 false /* override */,
                                 true /* inc_opt */);
+out:
+       dev_put(netdev);
 }
 
 static bool is_neigh_solicit(u8 *buf, size_t len)
index 549dbac710ed5f576f84cedf375df8588e5a7dc5..9a2bd11943ebf391a5678c7ded07ee0bc7b50f5e 100644 (file)
@@ -785,7 +785,7 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
            skb_out->len > CDC_NCM_MIN_TX_PKT)
                memset(skb_put(skb_out, ctx->tx_max - skb_out->len), 0,
                       ctx->tx_max - skb_out->len);
-       else if ((skb_out->len % dev->maxpacket) == 0)
+       else if (skb_out->len < ctx->tx_max && (skb_out->len % dev->maxpacket) == 0)
                *skb_put(skb_out, 1) = 0;       /* force short packet */
 
        /* set final frame length */
index e3458e3c44f146653048aba99295670caabd4db5..83208d4fdc5983aa963dbf1640732c17706ef9a2 100644 (file)
@@ -669,6 +669,22 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x05c6, 0x920d, 5)},
        {QMI_FIXED_INTF(0x12d1, 0x140c, 1)},    /* Huawei E173 */
        {QMI_FIXED_INTF(0x12d1, 0x14ac, 1)},    /* Huawei E1820 */
+       {QMI_FIXED_INTF(0x16d8, 0x6003, 0)},    /* CMOTech 6003 */
+       {QMI_FIXED_INTF(0x16d8, 0x6007, 0)},    /* CMOTech CHE-628S */
+       {QMI_FIXED_INTF(0x16d8, 0x6008, 0)},    /* CMOTech CMU-301 */
+       {QMI_FIXED_INTF(0x16d8, 0x6280, 0)},    /* CMOTech CHU-628 */
+       {QMI_FIXED_INTF(0x16d8, 0x7001, 0)},    /* CMOTech CHU-720S */
+       {QMI_FIXED_INTF(0x16d8, 0x7002, 0)},    /* CMOTech 7002 */
+       {QMI_FIXED_INTF(0x16d8, 0x7003, 4)},    /* CMOTech CHU-629K */
+       {QMI_FIXED_INTF(0x16d8, 0x7004, 3)},    /* CMOTech 7004 */
+       {QMI_FIXED_INTF(0x16d8, 0x7006, 5)},    /* CMOTech CGU-629 */
+       {QMI_FIXED_INTF(0x16d8, 0x700a, 4)},    /* CMOTech CHU-629S */
+       {QMI_FIXED_INTF(0x16d8, 0x7211, 0)},    /* CMOTech CHU-720I */
+       {QMI_FIXED_INTF(0x16d8, 0x7212, 0)},    /* CMOTech 7212 */
+       {QMI_FIXED_INTF(0x16d8, 0x7213, 0)},    /* CMOTech 7213 */
+       {QMI_FIXED_INTF(0x16d8, 0x7251, 1)},    /* CMOTech 7251 */
+       {QMI_FIXED_INTF(0x16d8, 0x7252, 1)},    /* CMOTech 7252 */
+       {QMI_FIXED_INTF(0x16d8, 0x7253, 1)},    /* CMOTech 7253 */
        {QMI_FIXED_INTF(0x19d2, 0x0002, 1)},
        {QMI_FIXED_INTF(0x19d2, 0x0012, 1)},
        {QMI_FIXED_INTF(0x19d2, 0x0017, 3)},
@@ -730,16 +746,28 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x114f, 0x68a2, 8)},    /* Sierra Wireless MC7750 */
        {QMI_FIXED_INTF(0x1199, 0x68a2, 8)},    /* Sierra Wireless MC7710 in QMI mode */
        {QMI_FIXED_INTF(0x1199, 0x68a2, 19)},   /* Sierra Wireless MC7710 in QMI mode */
+       {QMI_FIXED_INTF(0x1199, 0x68c0, 8)},    /* Sierra Wireless MC73xx */
+       {QMI_FIXED_INTF(0x1199, 0x68c0, 10)},   /* Sierra Wireless MC73xx */
+       {QMI_FIXED_INTF(0x1199, 0x68c0, 11)},   /* Sierra Wireless MC73xx */
        {QMI_FIXED_INTF(0x1199, 0x901c, 8)},    /* Sierra Wireless EM7700 */
+       {QMI_FIXED_INTF(0x1199, 0x901f, 8)},    /* Sierra Wireless EM7355 */
+       {QMI_FIXED_INTF(0x1199, 0x9041, 8)},    /* Sierra Wireless MC7305/MC7355 */
        {QMI_FIXED_INTF(0x1199, 0x9051, 8)},    /* Netgear AirCard 340U */
        {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)},    /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
+       {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)},    /* Alcatel L800MA */
        {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(0x1bc7, 0x1201, 2)},    /* Telit LE920 */
        {QMI_FIXED_INTF(0x0b3c, 0xc005, 6)},    /* Olivetti Olicard 200 */
+       {QMI_FIXED_INTF(0x0b3c, 0xc00b, 4)},    /* Olivetti Olicard 500 */
        {QMI_FIXED_INTF(0x1e2d, 0x0060, 4)},    /* Cinterion PLxx */
        {QMI_FIXED_INTF(0x1e2d, 0x0053, 4)},    /* Cinterion PHxx,PXxx */
+       {QMI_FIXED_INTF(0x413c, 0x81a2, 8)},    /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */
+       {QMI_FIXED_INTF(0x413c, 0x81a3, 8)},    /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */
+       {QMI_FIXED_INTF(0x413c, 0x81a4, 8)},    /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
+       {QMI_FIXED_INTF(0x413c, 0x81a8, 8)},    /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */
+       {QMI_FIXED_INTF(0x413c, 0x81a9, 8)},    /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
 
        /* 4. Gobi 1000 devices */
        {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},    /* Acer Gobi Modem Device */
index 7b687469199b58357a74490cb266e4d47534c097..8a852b5f215f1c5b3b42c3bc93cf6655a1178b68 100644 (file)
@@ -1285,7 +1285,7 @@ static int virtnet_set_channels(struct net_device *dev,
        if (channels->rx_count || channels->tx_count || channels->other_count)
                return -EINVAL;
 
-       if (queue_pairs > vi->max_queue_pairs)
+       if (queue_pairs > vi->max_queue_pairs || queue_pairs == 0)
                return -EINVAL;
 
        get_online_cpus();
index 82355d5d155a86921be733cc40deefcbaa6b7116..4dbb2ed85b972492e1dbbbdc51a81e32652f975b 100644 (file)
@@ -389,8 +389,8 @@ static inline size_t vxlan_nlmsg_size(void)
                + nla_total_size(sizeof(struct nda_cacheinfo));
 }
 
-static void vxlan_fdb_notify(struct vxlan_dev *vxlan,
-                            struct vxlan_fdb *fdb, int type)
+static void vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb,
+                            struct vxlan_rdst *rd, int type)
 {
        struct net *net = dev_net(vxlan->dev);
        struct sk_buff *skb;
@@ -400,8 +400,7 @@ static void vxlan_fdb_notify(struct vxlan_dev *vxlan,
        if (skb == NULL)
                goto errout;
 
-       err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0,
-                            first_remote_rtnl(fdb));
+       err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0, rd);
        if (err < 0) {
                /* -EMSGSIZE implies BUG in vxlan_nlmsg_size() */
                WARN_ON(err == -EMSGSIZE);
@@ -427,10 +426,7 @@ static void vxlan_ip_miss(struct net_device *dev, union vxlan_addr *ipa)
                .remote_vni = VXLAN_N_VID,
        };
 
-       INIT_LIST_HEAD(&f.remotes);
-       list_add_rcu(&remote.list, &f.remotes);
-
-       vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH);
+       vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH);
 }
 
 static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN])
@@ -438,11 +434,11 @@ static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN])
        struct vxlan_fdb f = {
                .state = NUD_STALE,
        };
+       struct vxlan_rdst remote = { };
 
-       INIT_LIST_HEAD(&f.remotes);
        memcpy(f.eth_addr, eth_addr, ETH_ALEN);
 
-       vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH);
+       vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH);
 }
 
 /* Hash Ethernet address */
@@ -533,7 +529,8 @@ static int vxlan_fdb_replace(struct vxlan_fdb *f,
 
 /* Add/update destinations for multicast */
 static int vxlan_fdb_append(struct vxlan_fdb *f,
-                           union vxlan_addr *ip, __be16 port, __u32 vni, __u32 ifindex)
+                           union vxlan_addr *ip, __be16 port, __u32 vni,
+                           __u32 ifindex, struct vxlan_rdst **rdp)
 {
        struct vxlan_rdst *rd;
 
@@ -551,6 +548,7 @@ static int vxlan_fdb_append(struct vxlan_fdb *f,
 
        list_add_tail_rcu(&rd->list, &f->remotes);
 
+       *rdp = rd;
        return 1;
 }
 
@@ -690,6 +688,7 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
                            __be16 port, __u32 vni, __u32 ifindex,
                            __u8 ndm_flags)
 {
+       struct vxlan_rdst *rd = NULL;
        struct vxlan_fdb *f;
        int notify = 0;
 
@@ -726,7 +725,8 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
                if ((flags & NLM_F_APPEND) &&
                    (is_multicast_ether_addr(f->eth_addr) ||
                     is_zero_ether_addr(f->eth_addr))) {
-                       int rc = vxlan_fdb_append(f, ip, port, vni, ifindex);
+                       int rc = vxlan_fdb_append(f, ip, port, vni, ifindex,
+                                                 &rd);
 
                        if (rc < 0)
                                return rc;
@@ -756,15 +756,18 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
                INIT_LIST_HEAD(&f->remotes);
                memcpy(f->eth_addr, mac, ETH_ALEN);
 
-               vxlan_fdb_append(f, ip, port, vni, ifindex);
+               vxlan_fdb_append(f, ip, port, vni, ifindex, &rd);
 
                ++vxlan->addrcnt;
                hlist_add_head_rcu(&f->hlist,
                                   vxlan_fdb_head(vxlan, mac));
        }
 
-       if (notify)
-               vxlan_fdb_notify(vxlan, f, RTM_NEWNEIGH);
+       if (notify) {
+               if (rd == NULL)
+                       rd = first_remote_rtnl(f);
+               vxlan_fdb_notify(vxlan, f, rd, RTM_NEWNEIGH);
+       }
 
        return 0;
 }
@@ -785,7 +788,7 @@ static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f)
                    "delete %pM\n", f->eth_addr);
 
        --vxlan->addrcnt;
-       vxlan_fdb_notify(vxlan, f, RTM_DELNEIGH);
+       vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_DELNEIGH);
 
        hlist_del_rcu(&f->hlist);
        call_rcu(&f->rcu, vxlan_fdb_free);
@@ -919,6 +922,7 @@ static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
         */
        if (rd && !list_is_singular(&f->remotes)) {
                list_del_rcu(&rd->list);
+               vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH);
                kfree_rcu(rd, rcu);
                goto out;
        }
@@ -993,7 +997,7 @@ static bool vxlan_snoop(struct net_device *dev,
 
                rdst->remote_ip = *src_ip;
                f->updated = jiffies;
-               vxlan_fdb_notify(vxlan, f, RTM_NEWNEIGH);
+               vxlan_fdb_notify(vxlan, f, rdst, RTM_NEWNEIGH);
        } else {
                /* learned new entry */
                spin_lock(&vxlan->hash_lock);
index a0398fe3eb284f94e650f4541e18bfcd6713e5ef..be3eb2a8d602ee9096cf2f7b798d4ea5807dba82 100644 (file)
@@ -86,7 +86,6 @@ static int ath_ahb_probe(struct platform_device *pdev)
        int irq;
        int ret = 0;
        struct ath_hw *ah;
-       struct ath_common *common;
        char hw_name[64];
 
        if (!dev_get_platdata(&pdev->dev)) {
@@ -146,9 +145,6 @@ static int ath_ahb_probe(struct platform_device *pdev)
        wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
                   hw_name, (unsigned long)mem, irq);
 
-       common = ath9k_hw_common(sc->sc_ah);
-       /* Will be cleared in ath9k_start() */
-       set_bit(ATH_OP_INVALID, &common->op_flags);
        return 0;
 
  err_irq:
index 6d47783f2e5b7ecfd4343c29c8ad4bcbff7252aa..ba502a2d199bc2c85e00718d7f1cda1f71e90e43 100644 (file)
@@ -155,6 +155,9 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel,
                ATH9K_ANI_RSSI_THR_LOW,
                ATH9K_ANI_RSSI_THR_HIGH);
 
+       if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_OFDM_DEF_LEVEL)
+               immunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
+
        if (!scan)
                aniState->ofdmNoiseImmunityLevel = immunityLevel;
 
@@ -235,6 +238,9 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel,
                BEACON_RSSI(ah), ATH9K_ANI_RSSI_THR_LOW,
                ATH9K_ANI_RSSI_THR_HIGH);
 
+       if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_CCK_DEF_LEVEL)
+               immunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
+
        if (ah->opmode == NL80211_IFTYPE_STATION &&
            BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_LOW &&
            immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
index 44d74495c4de1465dbf42cba08b6bff03090023a..3ba03dde42150b746bca7f2571a225e34d34af8e 100644 (file)
@@ -251,7 +251,6 @@ struct ath_atx_tid {
 
        s8 bar_index;
        bool sched;
-       bool paused;
        bool active;
 };
 
index d76e6e0120d2c28236163f56de4471c46f397c60..ffca918ff16aff4be941d572ac19d4f152e5b2c2 100644 (file)
@@ -72,7 +72,7 @@ static ssize_t read_file_node_aggr(struct file *file, char __user *user_buf,
                ath_txq_lock(sc, txq);
                if (tid->active) {
                        len += scnprintf(buf + len, size - len,
-                                        "%3d%11d%10d%10d%10d%10d%9d%6d%8d\n",
+                                        "%3d%11d%10d%10d%10d%10d%9d%6d\n",
                                         tid->tidno,
                                         tid->seq_start,
                                         tid->seq_next,
@@ -80,8 +80,7 @@ static ssize_t read_file_node_aggr(struct file *file, char __user *user_buf,
                                         tid->baw_head,
                                         tid->baw_tail,
                                         tid->bar_index,
-                                        tid->sched,
-                                        tid->paused);
+                                        tid->sched);
                }
                ath_txq_unlock(sc, txq);
        }
index f46cd0250e488217ca4aa517be12924e3b61c6a8..5627917c5ff761137061467e1b9d71f281ce0652 100644 (file)
@@ -95,8 +95,10 @@ static void ath9k_htc_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
 
        if ((vif->type == NL80211_IFTYPE_AP ||
             vif->type == NL80211_IFTYPE_MESH_POINT) &&
-           bss_conf->enable_beacon)
+           bss_conf->enable_beacon) {
                priv->reconfig_beacon = true;
+               priv->rearm_ani = true;
+       }
 
        if (bss_conf->assoc) {
                priv->rearm_ani = true;
@@ -257,6 +259,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
 
        ath9k_htc_ps_wakeup(priv);
 
+       ath9k_htc_stop_ani(priv);
        del_timer_sync(&priv->tx.cleanup_timer);
        ath9k_htc_tx_drain(priv);
 
index cbbb02a6b13b463c9bfdf8b1bad21f45cde0b4cd..36ae6490e5543af837f046f169115e3dd5d65d6b 100644 (file)
@@ -783,6 +783,9 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
        common = ath9k_hw_common(ah);
        ath9k_set_hw_capab(sc, hw);
 
+       /* Will be cleared in ath9k_start() */
+       set_bit(ATH_OP_INVALID, &common->op_flags);
+
        /* Initialize regulatory */
        error = ath_regd_init(&common->regulatory, sc->hw->wiphy,
                              ath9k_reg_notifier);
index 25304adece571d9d4e498df9398103a49ad08a7e..914dbc6b17208df991e92d3c3539508ea31f57ad 100644 (file)
@@ -784,7 +784,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct ath_softc *sc;
        struct ieee80211_hw *hw;
-       struct ath_common *common;
        u8 csz;
        u32 val;
        int ret = 0;
@@ -877,10 +876,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
                   hw_name, (unsigned long)sc->mem, pdev->irq);
 
-       /* Will be cleared in ath9k_start() */
-       common = ath9k_hw_common(sc->sc_ah);
-       set_bit(ATH_OP_INVALID, &common->op_flags);
-
        return 0;
 
 err_init:
index 6c9accdb52e4140076d7378f530e975c34f68433..19df969ec9093235eff8075d558e076edca2785a 100644 (file)
@@ -975,6 +975,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
        u64 tsf = 0;
        unsigned long flags;
        dma_addr_t new_buf_addr;
+       unsigned int budget = 512;
 
        if (edma)
                dma_type = DMA_BIDIRECTIONAL;
@@ -1113,15 +1114,17 @@ requeue_drop_frag:
                }
 requeue:
                list_add_tail(&bf->list, &sc->rx.rxbuf);
-               if (flush)
-                       continue;
 
                if (edma) {
                        ath_rx_edma_buf_link(sc, qtype);
                } else {
                        ath_rx_buf_relink(sc, bf);
-                       ath9k_hw_rxena(ah);
+                       if (!flush)
+                               ath9k_hw_rxena(ah);
                }
+
+               if (!budget--)
+                       break;
        } while (1);
 
        if (!(ah->imask & ATH9K_INT_RXEOL)) {
index 87cbec47fb48371403daaa70b32c1b9bc40ce1ec..66acb2cbd9df3cc45c307bb6b38118436da3d01a 100644 (file)
@@ -107,9 +107,6 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
 {
        struct ath_atx_ac *ac = tid->ac;
 
-       if (tid->paused)
-               return;
-
        if (tid->sched)
                return;
 
@@ -1407,7 +1404,6 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
        ath_tx_tid_change_state(sc, txtid);
 
        txtid->active = true;
-       txtid->paused = true;
        *ssn = txtid->seq_start = txtid->seq_next;
        txtid->bar_index = -1;
 
@@ -1427,7 +1423,6 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
 
        ath_txq_lock(sc, txq);
        txtid->active = false;
-       txtid->paused = false;
        ath_tx_flush_tid(sc, txtid);
        ath_tx_tid_change_state(sc, txtid);
        ath_txq_unlock_complete(sc, txq);
@@ -1487,7 +1482,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
                ath_txq_lock(sc, txq);
                ac->clear_ps_filter = true;
 
-               if (!tid->paused && ath_tid_has_buffered(tid)) {
+               if (ath_tid_has_buffered(tid)) {
                        ath_tx_queue_tid(txq, tid);
                        ath_txq_schedule(sc, txq);
                }
@@ -1510,7 +1505,6 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta,
        ath_txq_lock(sc, txq);
 
        tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
-       tid->paused = false;
 
        if (ath_tid_has_buffered(tid)) {
                ath_tx_queue_tid(txq, tid);
@@ -1544,8 +1538,6 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
                        continue;
 
                tid = ATH_AN_2_TID(an, i);
-               if (tid->paused)
-                       continue;
 
                ath_txq_lock(sc, tid->ac->txq);
                while (nframes > 0) {
@@ -1844,9 +1836,6 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
                        list_del(&tid->list);
                        tid->sched = false;
 
-                       if (tid->paused)
-                               continue;
-
                        if (ath_tx_sched_aggr(sc, txq, tid, &stop))
                                sent = true;
 
@@ -2698,7 +2687,6 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
                tid->baw_size  = WME_MAX_BA;
                tid->baw_head  = tid->baw_tail = 0;
                tid->sched     = false;
-               tid->paused    = false;
                tid->active        = false;
                __skb_queue_head_init(&tid->buf_q);
                __skb_queue_head_init(&tid->retry_q);
index df130ef53d1c4054f59f2fe10d197a80673000c9..c7c9f15c0fe08170ee2f953e9690a13e605a3291 100644 (file)
@@ -303,10 +303,10 @@ static void brcmf_chip_ai_coredisable(struct brcmf_core_priv *core,
 
        ci = core->chip;
 
-       /* if core is already in reset, just return */
+       /* if core is already in reset, skip reset */
        regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL);
        if ((regdata & BCMA_RESET_CTL_RESET) != 0)
-               return;
+               goto in_reset_configure;
 
        /* configure reset */
        ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,
@@ -322,6 +322,7 @@ static void brcmf_chip_ai_coredisable(struct brcmf_core_priv *core,
        SPINWAIT(ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) !=
                 BCMA_RESET_CTL_RESET, 300);
 
+in_reset_configure:
        /* in-reset configure */
        ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,
                         reset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
index afb3d15e38ff0379a99c5e2c534be23c57b94e38..be1985296bdc75e725cdc161aa4101cea4a19476 100644 (file)
@@ -4948,7 +4948,7 @@ static int brcmf_enable_bw40_2g(struct brcmf_if *ifp)
        if (!err) {
                /* only set 2G bandwidth using bw_cap command */
                band_bwcap.band = cpu_to_le32(WLC_BAND_2G);
-               band_bwcap.bw_cap = cpu_to_le32(WLC_BW_40MHZ_BIT);
+               band_bwcap.bw_cap = cpu_to_le32(WLC_BW_CAP_40MHZ);
                err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap,
                                               sizeof(band_bwcap));
        } else {
index fa858d548d13c0bd794b98dc4da2053893b460dc..0489314425cbdf4a4b782867644ee9a0a0ca4b63 100644 (file)
@@ -611,14 +611,14 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
                bt_cmd->flags |= cpu_to_le32(BT_COEX_SYNC2SCO);
 
        if (IWL_MVM_BT_COEX_CORUNNING) {
-               bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_CORUN_LUT_20 |
-                                                   BT_VALID_CORUN_LUT_40);
+               bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_CORUN_LUT_20 |
+                                                    BT_VALID_CORUN_LUT_40);
                bt_cmd->flags |= cpu_to_le32(BT_COEX_CORUNNING);
        }
 
        if (IWL_MVM_BT_COEX_MPLUT) {
                bt_cmd->flags |= cpu_to_le32(BT_COEX_MPLUT);
-               bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_MULTI_PRIO_LUT);
+               bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_MULTI_PRIO_LUT);
        }
 
        if (mvm->cfg->bt_shared_single_ant)
index 9426905de6b283dc0230cf51d5a694478da7797a..d73a89ecd78aa0963c40a268fc7dd8e3d7fbe29d 100644 (file)
@@ -183,9 +183,9 @@ enum iwl_scan_type {
  *     this number of packets were received (typically 1)
  * @passive2active: is auto switching from passive to active during scan allowed
  * @rxchain_sel_flags: RXON_RX_CHAIN_*
- * @max_out_time: in usecs, max out of serving channel time
+ * @max_out_time: in TUs, max out of serving channel time
  * @suspend_time: how long to pause scan when returning to service channel:
- *     bits 0-19: beacon interal in usecs (suspend before executing)
+ *     bits 0-19: beacon interal in TUs (suspend before executing)
  *     bits 20-23: reserved
  *     bits 24-31: number of beacons (suspend between channels)
  * @rxon_flags: RXON_FLG_*
@@ -383,8 +383,8 @@ enum scan_framework_client {
  * @quiet_plcp_th:     quiet channel num of packets threshold
  * @good_CRC_th:       passive to active promotion threshold
  * @rx_chain:          RXON rx chain.
- * @max_out_time:      max uSec to be out of assoceated channel
- * @suspend_time:      pause scan this long when returning to service channel
+ * @max_out_time:      max TUs to be out of assoceated channel
+ * @suspend_time:      pause scan this TUs when returning to service channel
  * @flags:             RXON flags
  * @filter_flags:      RXONfilter
  * @tx_cmd:            tx command for active scan; for 2GHz and for 5GHz.
index f0cebf12c7b8415a3c787d0cc77a9b2b1c2a15ef..b41dc84e9431e6c625d55a28d5cd3ca7a885cf08 100644 (file)
@@ -1007,7 +1007,7 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac,
        memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN);
        len = roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4);
 
-       ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_SYNC, len, cmd);
+       ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_ASYNC, len, cmd);
        if (ret)
                IWL_ERR(mvm, "mcast filter cmd error. ret=%d\n", ret);
 }
@@ -1023,7 +1023,7 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm)
        if (WARN_ON_ONCE(!mvm->mcast_filter_cmd))
                return;
 
-       ieee80211_iterate_active_interfaces(
+       ieee80211_iterate_active_interfaces_atomic(
                mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
                iwl_mvm_mc_iface_iterator, &iter_data);
 }
@@ -1807,6 +1807,11 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
 
        mutex_lock(&mvm->mutex);
 
+       if (!iwl_mvm_is_idle(mvm)) {
+               ret = -EBUSY;
+               goto out;
+       }
+
        switch (mvm->scan_status) {
        case IWL_MVM_SCAN_OS:
                IWL_DEBUG_SCAN(mvm, "Stopping previous scan for sched_scan\n");
index d564233a65da6157c1aaf16a099ddf94b3be933e..f1ec0986c3c912865f0d51e1056ec03c786d8cc2 100644 (file)
@@ -1003,6 +1003,9 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif)
        return mvmvif->low_latency;
 }
 
+/* Assoc status */
+bool iwl_mvm_is_idle(struct iwl_mvm *mvm);
+
 /* Thermal management and CT-kill */
 void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff);
 void iwl_mvm_tt_handler(struct iwl_mvm *mvm);
index 9f52c5b3f0ec0e9b2da5949f2af88bbcd13d89ce..e1c838899363b373d176a71bc32d02282d56c018 100644 (file)
@@ -1010,7 +1010,7 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
                return;
        }
 
-#ifdef CPTCFG_MAC80211_DEBUGFS
+#ifdef CONFIG_MAC80211_DEBUGFS
        /* Disable last tx check if we are debugging with fixed rate */
        if (lq_sta->dbg_fixed_rate) {
                IWL_DEBUG_RATE(mvm, "Fixed rate. avoid rate scaling\n");
index c91dc8498852c46653cc43fddb57c382d3d7f3f0..c28de54c75d400d551a0be87d4501cc98fb5967a 100644 (file)
@@ -277,51 +277,22 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm,
                                            IEEE80211_IFACE_ITER_NORMAL,
                                            iwl_mvm_scan_condition_iterator,
                                            &global_bound);
-       /*
-        * Under low latency traffic passive scan is fragmented meaning
-        * that dwell on a particular channel will be fragmented. Each fragment
-        * dwell time is 20ms and fragments period is 105ms. Skipping to next
-        * channel will be delayed by the same period - 105ms. So suspend_time
-        * parameter describing both fragments and channels skipping periods is
-        * set to 105ms. This value is chosen so that overall passive scan
-        * duration will not be too long. Max_out_time in this case is set to
-        * 70ms, so for active scanning operating channel will be left for 70ms
-        * while for passive still for 20ms (fragment dwell).
-        */
-       if (global_bound) {
-               if (!iwl_mvm_low_latency(mvm)) {
-                       params->suspend_time = ieee80211_tu_to_usec(100);
-                       params->max_out_time = ieee80211_tu_to_usec(600);
-               } else {
-                       params->suspend_time = ieee80211_tu_to_usec(105);
-                       /* P2P doesn't support fragmented passive scan, so
-                        * configure max_out_time to be at least longest dwell
-                        * time for passive scan.
-                        */
-                       if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p) {
-                               params->max_out_time = ieee80211_tu_to_usec(70);
-                               params->passive_fragmented = true;
-                       } else {
-                               u32 passive_dwell;
 
-                               /*
-                                * Use band G so that passive channel dwell time
-                                * will be assigned with maximum value.
-                                */
-                               band = IEEE80211_BAND_2GHZ;
-                               passive_dwell = iwl_mvm_get_passive_dwell(band);
-                               params->max_out_time =
-                                       ieee80211_tu_to_usec(passive_dwell);
-                       }
-               }
+       if (!global_bound)
+               goto not_bound;
+
+       params->suspend_time = 100;
+       params->max_out_time = 600;
+
+       if (iwl_mvm_low_latency(mvm)) {
+               params->suspend_time = 250;
+               params->max_out_time = 250;
        }
 
+not_bound:
+
        for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) {
-               if (params->passive_fragmented)
-                       params->dwell[band].passive = 20;
-               else
-                       params->dwell[band].passive =
-                               iwl_mvm_get_passive_dwell(band);
+               params->dwell[band].passive = iwl_mvm_get_passive_dwell(band);
                params->dwell[band].active = iwl_mvm_get_active_dwell(band,
                                                                      n_ssids);
        }
@@ -761,7 +732,7 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
        int band_2ghz = mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels;
        int band_5ghz = mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels;
        int head = 0;
-       int tail = band_2ghz + band_5ghz;
+       int tail = band_2ghz + band_5ghz - 1;
        u32 ssid_bitmap;
        int cmd_len;
        int ret;
index d619851745a19ba6d3bf605555fcdbd5a09f8341..2180902266ae6636513346df888c9d68abf0a57e 100644 (file)
@@ -644,3 +644,22 @@ bool iwl_mvm_low_latency(struct iwl_mvm *mvm)
 
        return result;
 }
+
+static void iwl_mvm_idle_iter(void *_data, u8 *mac, struct ieee80211_vif *vif)
+{
+       bool *idle = _data;
+
+       if (!vif->bss_conf.idle)
+               *idle = false;
+}
+
+bool iwl_mvm_is_idle(struct iwl_mvm *mvm)
+{
+       bool idle = true;
+
+       ieee80211_iterate_active_interfaces_atomic(
+                       mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+                       iwl_mvm_idle_iter, &idle);
+
+       return idle;
+}
index dcfd6d866d095081d7001795c4ec802c3044926f..2365553f1ef79d59c3e8598335e48eb43e5cfdcb 100644 (file)
@@ -1749,6 +1749,10 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
         * PCI Tx retries from interfering with C3 CPU state */
        pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
 
+       trans->dev = &pdev->dev;
+       trans_pcie->pci_dev = pdev;
+       iwl_disable_interrupts(trans);
+
        err = pci_enable_msi(pdev);
        if (err) {
                dev_err(&pdev->dev, "pci_enable_msi failed(0X%x)\n", err);
@@ -1760,8 +1764,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
                }
        }
 
-       trans->dev = &pdev->dev;
-       trans_pcie->pci_dev = pdev;
        trans->hw_rev = iwl_read32(trans, CSR_HW_REV);
        trans->hw_id = (pdev->device << 16) + pdev->subsystem_device;
        snprintf(trans->hw_id_str, sizeof(trans->hw_id_str),
@@ -1787,8 +1789,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
                goto out_pci_disable_msi;
        }
 
-       trans_pcie->inta_mask = CSR_INI_SET_MASK;
-
        if (iwl_pcie_alloc_ict(trans))
                goto out_free_cmd_pool;
 
@@ -1800,6 +1800,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
                goto out_free_ict;
        }
 
+       trans_pcie->inta_mask = CSR_INI_SET_MASK;
+
        return trans;
 
 out_free_ict:
index ddeb5a709aa36d6375e58597104f4cc3cb632d12..a87ee9b6585a72cdad0394d773b17a69a8b80298 100644 (file)
@@ -620,21 +620,19 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
                rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL,
                                      bss_conf->bssid);
 
-       /*
-        * Update the beacon. This is only required on USB devices. PCI
-        * devices fetch beacons periodically.
-        */
-       if (changes & BSS_CHANGED_BEACON && rt2x00_is_usb(rt2x00dev))
-               rt2x00queue_update_beacon(rt2x00dev, vif);
-
        /*
         * Start/stop beaconing.
         */
        if (changes & BSS_CHANGED_BEACON_ENABLED) {
                if (!bss_conf->enable_beacon && intf->enable_beacon) {
-                       rt2x00queue_clear_beacon(rt2x00dev, vif);
                        rt2x00dev->intf_beaconing--;
                        intf->enable_beacon = false;
+                       /*
+                        * Clear beacon in the H/W for this vif. This is needed
+                        * to disable beaconing on this particular interface
+                        * and keep it running on other interfaces.
+                        */
+                       rt2x00queue_clear_beacon(rt2x00dev, vif);
 
                        if (rt2x00dev->intf_beaconing == 0) {
                                /*
@@ -645,11 +643,15 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
                                rt2x00queue_stop_queue(rt2x00dev->bcn);
                                mutex_unlock(&intf->beacon_skb_mutex);
                        }
-
-
                } else if (bss_conf->enable_beacon && !intf->enable_beacon) {
                        rt2x00dev->intf_beaconing++;
                        intf->enable_beacon = true;
+                       /*
+                        * Upload beacon to the H/W. This is only required on
+                        * USB devices. PCI devices fetch beacons periodically.
+                        */
+                       if (rt2x00_is_usb(rt2x00dev))
+                               rt2x00queue_update_beacon(rt2x00dev, vif);
 
                        if (rt2x00dev->intf_beaconing == 1) {
                                /*
index 06ef47cd62038cc9695078441d545be0ca1b9348..5b4c225396f244cea599bade9755951daa7d15ec 100644 (file)
@@ -293,7 +293,7 @@ static void _rtl88ee_translate_rx_signal_stuff(struct ieee80211_hw *hw,
        u8 *psaddr;
        __le16 fc;
        u16 type, ufc;
-       bool match_bssid, packet_toself, packet_beacon, addr;
+       bool match_bssid, packet_toself, packet_beacon = false, addr;
 
        tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift;
 
index 68b5c7e92cfbc2c6a76580a2d1dbb3297730c64f..07cb06da67297244131394e60fa19c9ddf86044e 100644 (file)
@@ -1001,7 +1001,7 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw)
        err = _rtl92cu_init_mac(hw);
        if (err) {
                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "init mac failed!\n");
-               return err;
+               goto exit;
        }
        err = rtl92c_download_fw(hw);
        if (err) {
index 36b48be8329c08dad5474f43600f2b11d8fcf279..2b3c78baa9f8b3742020aa377b0449785eeb8ab7 100644 (file)
@@ -49,6 +49,12 @@ static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb,       u8 skb_queue)
        if (ieee80211_is_nullfunc(fc))
                return QSLT_HIGH;
 
+       /* Kernel commit 1bf4bbb4024dcdab changed EAPOL packets to use
+        * queue V0 at priority 7; however, the RTL8192SE appears to have
+        * that queue at priority 6
+        */
+       if (skb->priority == 7)
+               return QSLT_VO;
        return skb->priority;
 }
 
index 630a3fcf65bc8113fd6b67ce587f26fbf46c9774..0d4a285cbd7edb45408360a83952ab288debf62d 100644 (file)
@@ -226,7 +226,7 @@ int xenvif_map_frontend_rings(struct xenvif *vif,
                              grant_ref_t rx_ring_ref);
 
 /* Check for SKBs from frontend and schedule backend processing */
-void xenvif_check_rx_xenvif(struct xenvif *vif);
+void xenvif_napi_schedule_or_enable_events(struct xenvif *vif);
 
 /* Prevent the device from generating any further traffic. */
 void xenvif_carrier_off(struct xenvif *vif);
index ef05c5c49d413d5bb23a3e4adbff88cb0c9ad7cd..20e9defa10606d7d54a0a5412eb93365ce748f5c 100644 (file)
@@ -75,32 +75,8 @@ static int xenvif_poll(struct napi_struct *napi, int budget)
        work_done = xenvif_tx_action(vif, budget);
 
        if (work_done < budget) {
-               int more_to_do = 0;
-               unsigned long flags;
-
-               /* It is necessary to disable IRQ before calling
-                * RING_HAS_UNCONSUMED_REQUESTS. Otherwise we might
-                * lose event from the frontend.
-                *
-                * Consider:
-                *   RING_HAS_UNCONSUMED_REQUESTS
-                *   <frontend generates event to trigger napi_schedule>
-                *   __napi_complete
-                *
-                * This handler is still in scheduled state so the
-                * event has no effect at all. After __napi_complete
-                * this handler is descheduled and cannot get
-                * scheduled again. We lose event in this case and the ring
-                * will be completely stalled.
-                */
-
-               local_irq_save(flags);
-
-               RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, more_to_do);
-               if (!more_to_do)
-                       __napi_complete(napi);
-
-               local_irq_restore(flags);
+               napi_complete(napi);
+               xenvif_napi_schedule_or_enable_events(vif);
        }
 
        return work_done;
@@ -194,7 +170,7 @@ static void xenvif_up(struct xenvif *vif)
        enable_irq(vif->tx_irq);
        if (vif->tx_irq != vif->rx_irq)
                enable_irq(vif->rx_irq);
-       xenvif_check_rx_xenvif(vif);
+       xenvif_napi_schedule_or_enable_events(vif);
 }
 
 static void xenvif_down(struct xenvif *vif)
index 76665405c5aac32d57eeadf355007cbb2b50cbec..7367208ee8cdd8b324ce661b48aa69c1d884855b 100644 (file)
@@ -104,7 +104,7 @@ static inline unsigned long idx_to_kaddr(struct xenvif *vif,
 
 /* Find the containing VIF's structure from a pointer in pending_tx_info array
  */
-static inline struct xenvif* ubuf_to_vif(struct ubuf_info *ubuf)
+static inline struct xenvif *ubuf_to_vif(const struct ubuf_info *ubuf)
 {
        u16 pending_idx = ubuf->desc;
        struct pending_tx_info *temp =
@@ -322,6 +322,35 @@ static void xenvif_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb,
        }
 }
 
+/*
+ * Find the grant ref for a given frag in a chain of struct ubuf_info's
+ * skb: the skb itself
+ * i: the frag's number
+ * ubuf: a pointer to an element in the chain. It should not be NULL
+ *
+ * Returns a pointer to the element in the chain where the page were found. If
+ * not found, returns NULL.
+ * See the definition of callback_struct in common.h for more details about
+ * the chain.
+ */
+static const struct ubuf_info *xenvif_find_gref(const struct sk_buff *const skb,
+                                               const int i,
+                                               const struct ubuf_info *ubuf)
+{
+       struct xenvif *foreign_vif = ubuf_to_vif(ubuf);
+
+       do {
+               u16 pending_idx = ubuf->desc;
+
+               if (skb_shinfo(skb)->frags[i].page.p ==
+                   foreign_vif->mmap_pages[pending_idx])
+                       break;
+               ubuf = (struct ubuf_info *) ubuf->ctx;
+       } while (ubuf);
+
+       return ubuf;
+}
+
 /*
  * Prepare an SKB to be transmitted to the frontend.
  *
@@ -346,9 +375,8 @@ static int xenvif_gop_skb(struct sk_buff *skb,
        int head = 1;
        int old_meta_prod;
        int gso_type;
-       struct ubuf_info *ubuf = skb_shinfo(skb)->destructor_arg;
-       grant_ref_t foreign_grefs[MAX_SKB_FRAGS];
-       struct xenvif *foreign_vif = NULL;
+       const struct ubuf_info *ubuf = skb_shinfo(skb)->destructor_arg;
+       const struct ubuf_info *const head_ubuf = ubuf;
 
        old_meta_prod = npo->meta_prod;
 
@@ -386,19 +414,6 @@ static int xenvif_gop_skb(struct sk_buff *skb,
        npo->copy_off = 0;
        npo->copy_gref = req->gref;
 
-       if ((skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) &&
-                (ubuf->callback == &xenvif_zerocopy_callback)) {
-               int i = 0;
-               foreign_vif = ubuf_to_vif(ubuf);
-
-               do {
-                       u16 pending_idx = ubuf->desc;
-                       foreign_grefs[i++] =
-                               foreign_vif->pending_tx_info[pending_idx].req.gref;
-                       ubuf = (struct ubuf_info *) ubuf->ctx;
-               } while (ubuf);
-       }
-
        data = skb->data;
        while (data < skb_tail_pointer(skb)) {
                unsigned int offset = offset_in_page(data);
@@ -415,13 +430,60 @@ static int xenvif_gop_skb(struct sk_buff *skb,
        }
 
        for (i = 0; i < nr_frags; i++) {
+               /* This variable also signals whether foreign_gref has a real
+                * value or not.
+                */
+               struct xenvif *foreign_vif = NULL;
+               grant_ref_t foreign_gref;
+
+               if ((skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) &&
+                       (ubuf->callback == &xenvif_zerocopy_callback)) {
+                       const struct ubuf_info *const startpoint = ubuf;
+
+                       /* Ideally ubuf points to the chain element which
+                        * belongs to this frag. Or if frags were removed from
+                        * the beginning, then shortly before it.
+                        */
+                       ubuf = xenvif_find_gref(skb, i, ubuf);
+
+                       /* Try again from the beginning of the list, if we
+                        * haven't tried from there. This only makes sense in
+                        * the unlikely event of reordering the original frags.
+                        * For injected local pages it's an unnecessary second
+                        * run.
+                        */
+                       if (unlikely(!ubuf) && startpoint != head_ubuf)
+                               ubuf = xenvif_find_gref(skb, i, head_ubuf);
+
+                       if (likely(ubuf)) {
+                               u16 pending_idx = ubuf->desc;
+
+                               foreign_vif = ubuf_to_vif(ubuf);
+                               foreign_gref = foreign_vif->pending_tx_info[pending_idx].req.gref;
+                               /* Just a safety measure. If this was the last
+                                * element on the list, the for loop will
+                                * iterate again if a local page were added to
+                                * the end. Using head_ubuf here prevents the
+                                * second search on the chain. Or the original
+                                * frags changed order, but that's less likely.
+                                * In any way, ubuf shouldn't be NULL.
+                                */
+                               ubuf = ubuf->ctx ?
+                                       (struct ubuf_info *) ubuf->ctx :
+                                       head_ubuf;
+                       } else
+                               /* This frag was a local page, added to the
+                                * array after the skb left netback.
+                                */
+                               ubuf = head_ubuf;
+               }
                xenvif_gop_frag_copy(vif, skb, npo,
                                     skb_frag_page(&skb_shinfo(skb)->frags[i]),
                                     skb_frag_size(&skb_shinfo(skb)->frags[i]),
                                     skb_shinfo(skb)->frags[i].page_offset,
                                     &head,
                                     foreign_vif,
-                                    foreign_grefs[i]);
+                                    foreign_vif ? foreign_gref : UINT_MAX);
        }
 
        return npo->meta_prod - old_meta_prod;
@@ -654,7 +716,7 @@ done:
                notify_remote_via_irq(vif->rx_irq);
 }
 
-void xenvif_check_rx_xenvif(struct xenvif *vif)
+void xenvif_napi_schedule_or_enable_events(struct xenvif *vif)
 {
        int more_to_do;
 
@@ -688,7 +750,7 @@ static void tx_credit_callback(unsigned long data)
 {
        struct xenvif *vif = (struct xenvif *)data;
        tx_add_credit(vif);
-       xenvif_check_rx_xenvif(vif);
+       xenvif_napi_schedule_or_enable_events(vif);
 }
 
 static void xenvif_tx_err(struct xenvif *vif,
index 6d4ee22708c93791d53860c0243d6a9258678283..32e969d9531909e575a37b80fb0debd3f4ae73d2 100644 (file)
@@ -1831,6 +1831,10 @@ int of_update_property(struct device_node *np, struct property *newprop)
        if (!found)
                return -ENODEV;
 
+       /* At early boot, bail out and defer setup to of_init() */
+       if (!of_kset)
+               return found ? 0 : -ENODEV;
+
        /* Update the sysfs attribute */
        sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
        __of_add_property_sysfs(np, newprop);
index d3d1cfd51e095f058404d96f063df76d227bd652..e384e2534594731a95eb7524fb75583fce208541 100644 (file)
@@ -293,6 +293,58 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
        return PCIBIOS_SUCCESSFUL;
 }
 
+/*
+ * Remove windows, starting from the largest ones to the smallest
+ * ones.
+ */
+static void mvebu_pcie_del_windows(struct mvebu_pcie_port *port,
+                                  phys_addr_t base, size_t size)
+{
+       while (size) {
+               size_t sz = 1 << (fls(size) - 1);
+
+               mvebu_mbus_del_window(base, sz);
+               base += sz;
+               size -= sz;
+       }
+}
+
+/*
+ * MBus windows can only have a power of two size, but PCI BARs do not
+ * have this constraint. Therefore, we have to split the PCI BAR into
+ * areas each having a power of two size. We start from the largest
+ * one (i.e highest order bit set in the size).
+ */
+static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port,
+                                  unsigned int target, unsigned int attribute,
+                                  phys_addr_t base, size_t size,
+                                  phys_addr_t remap)
+{
+       size_t size_mapped = 0;
+
+       while (size) {
+               size_t sz = 1 << (fls(size) - 1);
+               int ret;
+
+               ret = mvebu_mbus_add_window_remap_by_id(target, attribute, base,
+                                                       sz, remap);
+               if (ret) {
+                       dev_err(&port->pcie->pdev->dev,
+                               "Could not create MBus window at 0x%x, size 0x%x: %d\n",
+                               base, sz, ret);
+                       mvebu_pcie_del_windows(port, base - size_mapped,
+                                              size_mapped);
+                       return;
+               }
+
+               size -= sz;
+               size_mapped += sz;
+               base += sz;
+               if (remap != MVEBU_MBUS_NO_REMAP)
+                       remap += sz;
+       }
+}
+
 static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
 {
        phys_addr_t iobase;
@@ -304,8 +356,8 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
 
                /* If a window was configured, remove it */
                if (port->iowin_base) {
-                       mvebu_mbus_del_window(port->iowin_base,
-                                             port->iowin_size);
+                       mvebu_pcie_del_windows(port, port->iowin_base,
+                                              port->iowin_size);
                        port->iowin_base = 0;
                        port->iowin_size = 0;
                }
@@ -331,11 +383,11 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
        port->iowin_base = port->pcie->io.start + iobase;
        port->iowin_size = ((0xFFF | ((port->bridge.iolimit & 0xF0) << 8) |
                            (port->bridge.iolimitupper << 16)) -
-                           iobase);
+                           iobase) + 1;
 
-       mvebu_mbus_add_window_remap_by_id(port->io_target, port->io_attr,
-                                         port->iowin_base, port->iowin_size,
-                                         iobase);
+       mvebu_pcie_add_windows(port, port->io_target, port->io_attr,
+                              port->iowin_base, port->iowin_size,
+                              iobase);
 }
 
 static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
@@ -346,8 +398,8 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
 
                /* If a window was configured, remove it */
                if (port->memwin_base) {
-                       mvebu_mbus_del_window(port->memwin_base,
-                                             port->memwin_size);
+                       mvebu_pcie_del_windows(port, port->memwin_base,
+                                              port->memwin_size);
                        port->memwin_base = 0;
                        port->memwin_size = 0;
                }
@@ -364,10 +416,11 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
        port->memwin_base  = ((port->bridge.membase & 0xFFF0) << 16);
        port->memwin_size  =
                (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) -
-               port->memwin_base;
+               port->memwin_base + 1;
 
-       mvebu_mbus_add_window_by_id(port->mem_target, port->mem_attr,
-                                   port->memwin_base, port->memwin_size);
+       mvebu_pcie_add_windows(port, port->mem_target, port->mem_attr,
+                              port->memwin_base, port->memwin_size,
+                              MVEBU_MBUS_NO_REMAP);
 }
 
 /*
@@ -743,14 +796,21 @@ static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
 
        /*
         * On the PCI-to-PCI bridge side, the I/O windows must have at
-        * least a 64 KB size and be aligned on their size, and the
-        * memory windows must have at least a 1 MB size and be
-        * aligned on their size
+        * least a 64 KB size and the memory windows must have at
+        * least a 1 MB size. Moreover, MBus windows need to have a
+        * base address aligned on their size, and their size must be
+        * a power of two. This means that if the BAR doesn't have a
+        * power of two size, several MBus windows will actually be
+        * created. We need to ensure that the biggest MBus window
+        * (which will be the first one) is aligned on its size, which
+        * explains the rounddown_pow_of_two() being done here.
         */
        if (res->flags & IORESOURCE_IO)
-               return round_up(start, max_t(resource_size_t, SZ_64K, size));
+               return round_up(start, max_t(resource_size_t, SZ_64K,
+                                            rounddown_pow_of_two(size)));
        else if (res->flags & IORESOURCE_MEM)
-               return round_up(start, max_t(resource_size_t, SZ_1M, size));
+               return round_up(start, max_t(resource_size_t, SZ_1M,
+                                            rounddown_pow_of_two(size)));
        else
                return start;
 }
index 58499277903a4ab4a6225982d88876de399120e2..6efc2ec5e4db0823758a409eb95c2d3054a8ba48 100644 (file)
@@ -282,8 +282,8 @@ static int board_added(struct slot *p_slot)
                return WRONG_BUS_FREQUENCY;
        }
 
-       bsp = ctrl->pci_dev->bus->cur_bus_speed;
-       msp = ctrl->pci_dev->bus->max_bus_speed;
+       bsp = ctrl->pci_dev->subordinate->cur_bus_speed;
+       msp = ctrl->pci_dev->subordinate->max_bus_speed;
 
        /* Check if there are other slots or devices on the same bus */
        if (!list_empty(&ctrl->pci_dev->subordinate->devices))
index 7325d43bf030ce65d5f386f6aeeeb3bfa4d5c482..759475ef6ff3206bd04103043cfed21092766493 100644 (file)
@@ -3067,7 +3067,8 @@ int pci_wait_for_pending_transaction(struct pci_dev *dev)
        if (!pci_is_pcie(dev))
                return 1;
 
-       return pci_wait_for_pending(dev, PCI_EXP_DEVSTA, PCI_EXP_DEVSTA_TRPND);
+       return pci_wait_for_pending(dev, pci_pcie_cap(dev) + PCI_EXP_DEVSTA,
+                                   PCI_EXP_DEVSTA_TRPND);
 }
 EXPORT_SYMBOL(pci_wait_for_pending_transaction);
 
@@ -3109,7 +3110,7 @@ static int pci_af_flr(struct pci_dev *dev, int probe)
                return 0;
 
        /* Wait for Transaction Pending bit clean */
-       if (pci_wait_for_pending(dev, PCI_AF_STATUS, PCI_AF_STATUS_TP))
+       if (pci_wait_for_pending(dev, pos + PCI_AF_STATUS, PCI_AF_STATUS_TP))
                goto clear;
 
        dev_err(&dev->dev, "transaction is not cleared; "
index 9802b67040cc6a49a1e4f8df15db337ae912b778..2c61281bebd7666f6b12e87a7618c47a3a3aae18 100644 (file)
@@ -523,17 +523,6 @@ static int wmt_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
                return GPIOF_DIR_IN;
 }
 
-static int wmt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-       return pinctrl_gpio_direction_input(chip->base + offset);
-}
-
-static int wmt_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
-                                    int value)
-{
-       return pinctrl_gpio_direction_output(chip->base + offset);
-}
-
 static int wmt_gpio_get_value(struct gpio_chip *chip, unsigned offset)
 {
        struct wmt_pinctrl_data *data = dev_get_drvdata(chip->dev);
@@ -568,6 +557,18 @@ static void wmt_gpio_set_value(struct gpio_chip *chip, unsigned offset,
                wmt_clearbits(data, reg_data_out, BIT(bit));
 }
 
+static int wmt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       return pinctrl_gpio_direction_input(chip->base + offset);
+}
+
+static int wmt_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+                                    int value)
+{
+       wmt_gpio_set_value(chip, offset, value);
+       return pinctrl_gpio_direction_output(chip->base + offset);
+}
+
 static struct gpio_chip wmt_gpio_chip = {
        .label = "gpio-wmt",
        .owner = THIS_MODULE,
index deb7f4bcdb7b6b6a770ce08f1d2535dccfa82100..438d4c72c7b36c27982ed8e60b9a42cbff58dc8f 100644 (file)
@@ -37,7 +37,7 @@ __visible struct {
  * kernel begins at offset 3GB...
  */
 
-asmlinkage void pnp_bios_callfunc(void);
+asmlinkage __visible void pnp_bios_callfunc(void);
 
 __asm__(".text                 \n"
        __ALIGN_STR "\n"
index 6963bdf5417593921122694d8ae425ff7a599f7e..6aea373547f65f3743faa7236b5035a83e178966 100644 (file)
@@ -6,6 +6,7 @@ menu "PTP clock support"
 
 config PTP_1588_CLOCK
        tristate "PTP clock support"
+       depends on NET
        select PPS
        select NET_PTP_CLASSIFY
        help
@@ -74,7 +75,7 @@ config DP83640_PHY
 config PTP_1588_CLOCK_PCH
        tristate "Intel PCH EG20T as PTP clock"
        depends on X86 || COMPILE_TEST
-       depends on HAS_IOMEM
+       depends on HAS_IOMEM && NET
        select PTP_1588_CLOCK
        help
          This driver adds support for using the PCH EG20T as a PTP
index bd628a6f981d8b550c7e651c845232fcaf5a57ff..e5f13c4310feb368b5855269a043c88bc698da74 100644 (file)
@@ -569,6 +569,9 @@ static int hym8563_probe(struct i2c_client *client,
        if (IS_ERR(hym8563->rtc))
                return PTR_ERR(hym8563->rtc);
 
+       /* the hym8563 alarm only supports a minute accuracy */
+       hym8563->rtc->uie_unsupported = 1;
+
 #ifdef CONFIG_COMMON_CLK
        hym8563_clkout_register_clk(hym8563);
 #endif
index 5c8f8226c8485af61dc6b82b52c56861619a3f52..4cdb64be061bd7d175417581010d7f702ed6b006 100644 (file)
@@ -206,7 +206,7 @@ static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm)
        tm->tm_hour = bcd2bin(regs[2] & 0x3f);
        tm->tm_mday = bcd2bin(regs[3] & 0x3f);
        tm->tm_wday = regs[4] & 0x7;
-       tm->tm_mon = bcd2bin(regs[5] & 0x1f);
+       tm->tm_mon = bcd2bin(regs[5] & 0x1f) - 1;
        tm->tm_year = bcd2bin(regs[6]) + 100;
 
        return rtc_valid_tm(tm);
@@ -229,7 +229,7 @@ static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm)
        regs[3] = bin2bcd(tm->tm_hour);
        regs[4] = bin2bcd(tm->tm_mday);
        regs[5] = tm->tm_wday;
-       regs[6] = bin2bcd(tm->tm_mon);
+       regs[6] = bin2bcd(tm->tm_mon + 1);
        regs[7] = bin2bcd(tm->tm_year - 100);
 
        msg.addr = client->addr;
index 296c936cc03cc43397ba4905d53ac1fd7b050f89..a8d721ff19ebff8b5f11e4cfc1b17e715defec30 100644 (file)
@@ -639,7 +639,7 @@ static int __init atari_scsi_detect(struct scsi_host_template *host)
                                        "double buffer\n");
                        return 0;
                }
-               atari_dma_phys_buffer = virt_to_phys(atari_dma_buffer);
+               atari_dma_phys_buffer = atari_stram_to_phys(atari_dma_buffer);
                atari_dma_orig_addr = 0;
        }
 #endif
index fe30ea94ffe67ef4e5d355fdc9cdcb71eee9e0d7..109802f776ed71cea6857eda9ae6ccc3e0b41f80 100644 (file)
@@ -77,7 +77,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
                        goto next_msg;
                }
 
-               if (!capable(CAP_SYS_ADMIN)) {
+               if (!netlink_capable(skb, CAP_SYS_ADMIN)) {
                        err = -EPERM;
                        goto next_msg;
                }
index 1b681427dde045cdad8f2455c07467fba4f077f1..c341f855fadcd433a6730db0d941317615a7fe9e 100644 (file)
@@ -1621,8 +1621,6 @@ void sas_rphy_free(struct sas_rphy *rphy)
        list_del(&rphy->list);
        mutex_unlock(&sas_host->lock);
 
-       sas_bsg_remove(shost, rphy);
-
        transport_destroy_device(dev);
 
        put_device(dev);
@@ -1681,6 +1679,7 @@ sas_rphy_remove(struct sas_rphy *rphy)
        }
 
        sas_rphy_unlink(rphy);
+       sas_bsg_remove(NULL, rphy);
        transport_remove_device(dev);
        device_del(dev);
 }
index fc67f564f02cf77eec2350f4435836d409020314..788ed9b59b4e3f04c3a485fefe6d31dfdb6b681f 100644 (file)
@@ -1,10 +1,12 @@
 #
 # Makefile for the SuperH specific drivers.
 #
-obj-y  := intc/
+obj-$(CONFIG_SUPERH)                   += intc/
+obj-$(CONFIG_ARCH_SHMOBILE_LEGACY)     += intc/
+ifneq ($(CONFIG_COMMON_CLK),y)
+obj-$(CONFIG_HAVE_CLK)                 += clk/
+endif
+obj-$(CONFIG_MAPLE)                    += maple/
+obj-$(CONFIG_SUPERHYWAY)               += superhyway/
 
-obj-$(CONFIG_HAVE_CLK)         += clk/
-obj-$(CONFIG_MAPLE)            += maple/
-obj-$(CONFIG_SUPERHYWAY)       += superhyway/
-
-obj-y                          += pm_runtime.o
+obj-y                                  += pm_runtime.o
index 8afa5a4589f2dd03771acaac8be585447e8033c0..10c65eb51f8587ca79b15291a75c04c16e4604a2 100644 (file)
@@ -50,8 +50,25 @@ static struct pm_clk_notifier_block platform_bus_notifier = {
        .con_ids = { NULL, },
 };
 
+static bool default_pm_on;
+
 static int __init sh_pm_runtime_init(void)
 {
+       if (IS_ENABLED(CONFIG_ARCH_SHMOBILE_MULTI)) {
+               if (!of_machine_is_compatible("renesas,emev2") &&
+                   !of_machine_is_compatible("renesas,r7s72100") &&
+                   !of_machine_is_compatible("renesas,r8a73a4") &&
+                   !of_machine_is_compatible("renesas,r8a7740") &&
+                   !of_machine_is_compatible("renesas,r8a7778") &&
+                   !of_machine_is_compatible("renesas,r8a7779") &&
+                   !of_machine_is_compatible("renesas,r8a7790") &&
+                   !of_machine_is_compatible("renesas,r8a7791") &&
+                   !of_machine_is_compatible("renesas,sh7372") &&
+                   !of_machine_is_compatible("renesas,sh73a0"))
+                       return 0;
+       }
+
+       default_pm_on = true;
        pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
        return 0;
 }
@@ -59,7 +76,8 @@ core_initcall(sh_pm_runtime_init);
 
 static int __init sh_pm_runtime_late_init(void)
 {
-       pm_genpd_poweroff_unused();
+       if (default_pm_on)
+               pm_genpd_poweroff_unused();
        return 0;
 }
 late_initcall(sh_pm_runtime_late_init);
index 713af4806f265e10b87dcfade6b6989055c2f283..f6759dc0153b4a8c45fb83f7660e34be2a47641b 100644 (file)
@@ -29,18 +29,6 @@ static int pxa2xx_spi_map_dma_buffer(struct driver_data *drv_data,
        struct sg_table *sgt;
        void *buf, *pbuf;
 
-       /*
-        * Some DMA controllers have problems transferring buffers that are
-        * not multiple of 4 bytes. So we truncate the transfer so that it
-        * is suitable for such controllers, and handle the trailing bytes
-        * manually after the DMA completes.
-        *
-        * REVISIT: It would be better if this information could be
-        * retrieved directly from the DMA device in a similar way than
-        * ->copy_align etc. is done.
-        */
-       len = ALIGN(drv_data->len, 4);
-
        if (dir == DMA_TO_DEVICE) {
                dmadev = drv_data->tx_chan->device->dev;
                sgt = &drv_data->tx_sgt;
@@ -144,12 +132,8 @@ static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data,
                if (!error) {
                        pxa2xx_spi_unmap_dma_buffers(drv_data);
 
-                       /* Handle the last bytes of unaligned transfer */
                        drv_data->tx += drv_data->tx_map_len;
-                       drv_data->write(drv_data);
-
                        drv_data->rx += drv_data->rx_map_len;
-                       drv_data->read(drv_data);
 
                        msg->actual_length += drv_data->len;
                        msg->state = pxa2xx_spi_next_transfer(drv_data);
index b032e8885e2435b3585810f1266bca9aa3fce6a8..78c66e3c53ed5f88d8d79ac3c16cdb4800af71f0 100644 (file)
@@ -734,7 +734,7 @@ static int spi_qup_remove(struct platform_device *pdev)
        int ret;
 
        ret = pm_runtime_get_sync(&pdev->dev);
-       if (ret)
+       if (ret < 0)
                return ret;
 
        ret = spi_qup_set_state(controller, QUP_STATE_RESET);
index 4eb9bf02996cf179cf3e6365421867aaf8a10593..939edf473235dca2fb7692fe0fec6dbdd649bbd0 100644 (file)
@@ -580,6 +580,7 @@ static void spi_set_cs(struct spi_device *spi, bool enable)
                spi->master->set_cs(spi, !enable);
 }
 
+#ifdef CONFIG_HAS_DMA
 static int spi_map_buf(struct spi_master *master, struct device *dev,
                       struct sg_table *sgt, void *buf, size_t len,
                       enum dma_data_direction dir)
@@ -637,55 +638,12 @@ static void spi_unmap_buf(struct spi_master *master, struct device *dev,
        }
 }
 
-static int spi_map_msg(struct spi_master *master, struct spi_message *msg)
+static int __spi_map_msg(struct spi_master *master, struct spi_message *msg)
 {
        struct device *tx_dev, *rx_dev;
        struct spi_transfer *xfer;
-       void *tmp;
-       unsigned int max_tx, max_rx;
        int ret;
 
-       if (master->flags & (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX)) {
-               max_tx = 0;
-               max_rx = 0;
-
-               list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-                       if ((master->flags & SPI_MASTER_MUST_TX) &&
-                           !xfer->tx_buf)
-                               max_tx = max(xfer->len, max_tx);
-                       if ((master->flags & SPI_MASTER_MUST_RX) &&
-                           !xfer->rx_buf)
-                               max_rx = max(xfer->len, max_rx);
-               }
-
-               if (max_tx) {
-                       tmp = krealloc(master->dummy_tx, max_tx,
-                                      GFP_KERNEL | GFP_DMA);
-                       if (!tmp)
-                               return -ENOMEM;
-                       master->dummy_tx = tmp;
-                       memset(tmp, 0, max_tx);
-               }
-
-               if (max_rx) {
-                       tmp = krealloc(master->dummy_rx, max_rx,
-                                      GFP_KERNEL | GFP_DMA);
-                       if (!tmp)
-                               return -ENOMEM;
-                       master->dummy_rx = tmp;
-               }
-
-               if (max_tx || max_rx) {
-                       list_for_each_entry(xfer, &msg->transfers,
-                                           transfer_list) {
-                               if (!xfer->tx_buf)
-                                       xfer->tx_buf = master->dummy_tx;
-                               if (!xfer->rx_buf)
-                                       xfer->rx_buf = master->dummy_rx;
-                       }
-               }
-       }
-
        if (!master->can_dma)
                return 0;
 
@@ -742,6 +700,69 @@ static int spi_unmap_msg(struct spi_master *master, struct spi_message *msg)
 
        return 0;
 }
+#else /* !CONFIG_HAS_DMA */
+static inline int __spi_map_msg(struct spi_master *master,
+                               struct spi_message *msg)
+{
+       return 0;
+}
+
+static inline int spi_unmap_msg(struct spi_master *master,
+                               struct spi_message *msg)
+{
+       return 0;
+}
+#endif /* !CONFIG_HAS_DMA */
+
+static int spi_map_msg(struct spi_master *master, struct spi_message *msg)
+{
+       struct spi_transfer *xfer;
+       void *tmp;
+       unsigned int max_tx, max_rx;
+
+       if (master->flags & (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX)) {
+               max_tx = 0;
+               max_rx = 0;
+
+               list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+                       if ((master->flags & SPI_MASTER_MUST_TX) &&
+                           !xfer->tx_buf)
+                               max_tx = max(xfer->len, max_tx);
+                       if ((master->flags & SPI_MASTER_MUST_RX) &&
+                           !xfer->rx_buf)
+                               max_rx = max(xfer->len, max_rx);
+               }
+
+               if (max_tx) {
+                       tmp = krealloc(master->dummy_tx, max_tx,
+                                      GFP_KERNEL | GFP_DMA);
+                       if (!tmp)
+                               return -ENOMEM;
+                       master->dummy_tx = tmp;
+                       memset(tmp, 0, max_tx);
+               }
+
+               if (max_rx) {
+                       tmp = krealloc(master->dummy_rx, max_rx,
+                                      GFP_KERNEL | GFP_DMA);
+                       if (!tmp)
+                               return -ENOMEM;
+                       master->dummy_rx = tmp;
+               }
+
+               if (max_tx || max_rx) {
+                       list_for_each_entry(xfer, &msg->transfers,
+                                           transfer_list) {
+                               if (!xfer->tx_buf)
+                                       xfer->tx_buf = master->dummy_tx;
+                               if (!xfer->rx_buf)
+                                       xfer->rx_buf = master->dummy_rx;
+                       }
+               }
+       }
+
+       return __spi_map_msg(master, msg);
+}
 
 /*
  * spi_transfer_one_message - Default implementation of transfer_one_message()
@@ -1151,7 +1172,6 @@ static int spi_master_initialize_queue(struct spi_master *master)
 {
        int ret;
 
-       master->queued = true;
        master->transfer = spi_queued_transfer;
        if (!master->transfer_one_message)
                master->transfer_one_message = spi_transfer_one_message;
@@ -1162,6 +1182,7 @@ static int spi_master_initialize_queue(struct spi_master *master)
                dev_err(&master->dev, "problem initializing queue\n");
                goto err_init_queue;
        }
+       master->queued = true;
        ret = spi_start_queue(master);
        if (ret) {
                dev_err(&master->dev, "problem starting queue\n");
@@ -1171,8 +1192,8 @@ static int spi_master_initialize_queue(struct spi_master *master)
        return 0;
 
 err_start_queue:
-err_init_queue:
        spi_destroy_queue(master);
+err_init_queue:
        return ret;
 }
 
@@ -1756,7 +1777,7 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master);
  */
 int spi_setup(struct spi_device *spi)
 {
-       unsigned        bad_bits;
+       unsigned        bad_bits, ugly_bits;
        int             status = 0;
 
        /* check mode to prevent that DUAL and QUAD set at the same time
@@ -1776,6 +1797,15 @@ int spi_setup(struct spi_device *spi)
         * that aren't supported with their current master
         */
        bad_bits = spi->mode & ~spi->master->mode_bits;
+       ugly_bits = bad_bits &
+                   (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD);
+       if (ugly_bits) {
+               dev_warn(&spi->dev,
+                        "setup: ignoring unsupported mode bits %x\n",
+                        ugly_bits);
+               spi->mode &= ~ugly_bits;
+               bad_bits &= ~ugly_bits;
+       }
        if (bad_bits) {
                dev_err(&spi->dev, "setup: unsupported mode bits %x\n",
                        bad_bits);
index e2b482045158dedb9101f6939b1c4d5dbe071f7d..017d2f8379b78ca86f7e30ed0e85855684c7b6ec 100644 (file)
@@ -107,7 +107,7 @@ static int ad2s1200_probe(struct spi_device *spi)
        int pn, ret = 0;
        unsigned short *pins = spi->dev.platform_data;
 
-       for (pn = 0; pn < AD2S1200_PN; pn++)
+       for (pn = 0; pn < AD2S1200_PN; pn++) {
                ret = devm_gpio_request_one(&spi->dev, pins[pn], GPIOF_DIR_OUT,
                                            DRV_NAME);
                if (ret) {
@@ -115,6 +115,7 @@ static int ad2s1200_probe(struct spi_device *spi)
                                                        pins[pn]);
                        return ret;
                }
+       }
        indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
        if (!indio_dev)
                return -ENOMEM;
index 4144a75e5f71bc6258d9d8dcdc1a02b3b2a2f035..c270c9ae6d27711d531ebb54a07b1cdc125be9da 100644 (file)
@@ -517,7 +517,7 @@ int imx_drm_encoder_get_mux_id(struct device_node *node,
                of_node_put(port);
                if (port == imx_crtc->port) {
                        ret = of_graph_parse_endpoint(ep, &endpoint);
-                       return ret ? ret : endpoint.id;
+                       return ret ? ret : endpoint.port;
                }
        } while (ep);
 
@@ -675,6 +675,11 @@ static int imx_drm_platform_probe(struct platform_device *pdev)
                        if (!remote || !of_device_is_available(remote)) {
                                of_node_put(remote);
                                continue;
+                       } else if (!of_device_is_available(remote->parent)) {
+                               dev_warn(&pdev->dev, "parent device of %s is not available\n",
+                                        remote->full_name);
+                               of_node_put(remote);
+                               continue;
                        }
 
                        ret = imx_drm_add_component(&pdev->dev, remote);
index 575533f4fd64fc7d53d38c4a0cb307fa429f9f68..a23f4f773146a8891925165622cb5167d30252df 100644 (file)
@@ -582,7 +582,7 @@ static int imx_tve_bind(struct device *dev, struct device *master, void *data)
        tve->dev = dev;
        spin_lock_init(&tve->lock);
 
-       ddc_node = of_parse_phandle(np, "i2c-ddc-bus", 0);
+       ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
        if (ddc_node) {
                tve->ddc = of_find_i2c_adapter_by_node(ddc_node);
                of_node_put(ddc_node);
index 8c101cbbee97646d2b06166865381bf9144df2cb..acc8184c46cde0d85ebeccd41c000b67ae9da429 100644 (file)
@@ -1247,9 +1247,18 @@ static int vpfe_stop_streaming(struct vb2_queue *vq)
        struct vpfe_fh *fh = vb2_get_drv_priv(vq);
        struct vpfe_video_device *video = fh->video;
 
-       if (!vb2_is_streaming(vq))
-               return 0;
        /* release all active buffers */
+       if (video->cur_frm == video->next_frm) {
+               vb2_buffer_done(&video->cur_frm->vb, VB2_BUF_STATE_ERROR);
+       } else {
+               if (video->cur_frm != NULL)
+                       vb2_buffer_done(&video->cur_frm->vb,
+                                       VB2_BUF_STATE_ERROR);
+               if (video->next_frm != NULL)
+                       vb2_buffer_done(&video->next_frm->vb,
+                                       VB2_BUF_STATE_ERROR);
+       }
+
        while (!list_empty(&video->dma_queue)) {
                video->next_frm = list_entry(video->dma_queue.next,
                                                struct vpfe_cap_buffer, list);
index b3d2cc729657df34e57bc300033bafc1baf2bdd6..4ba569258498b9d6248de4d58d13c63750c68561 100644 (file)
@@ -48,10 +48,8 @@ static const struct usb_device_id sn9c102_id_table[] = {
        { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), },
 /*     { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */
        { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), },
-#endif
        { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), },
        { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), },
-#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
        { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), },
        { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), },
        { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), },
index 57eca7a45672b94674677f88cfef688ca403c386..4fe751f7c2bf2438f0e49054731d911c4e84d239 100644 (file)
@@ -953,8 +953,6 @@ static int netdev_close(struct net_device *pnetdev)
 #endif /* CONFIG_8723AU_P2P */
 
        rtw_scan_abort23a(padapter);
-        /* set this at the end */
-       padapter->rtw_wdev->iftype = NL80211_IFTYPE_MONITOR;
 
        RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-871x_drv - drv_close\n"));
        DBG_8723A("-871x_drv - drv_close, bup =%d\n", padapter->bup);
index c49160e477d8d0245392fea0db2a2d432c186b2f..07e542e5d1562b18fa3caad2903b0928dccdd1e2 100644 (file)
@@ -26,7 +26,7 @@ unsigned int ffaddr2pipehdl23a(struct dvobj_priv *pdvobj, u32 addr)
        if (addr == RECV_BULK_IN_ADDR) {
                pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[0]);
        } else if (addr == RECV_INT_IN_ADDR) {
-               pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[1]);
+               pipe = usb_rcvintpipe(pusbd, pdvobj->RtInPipe[1]);
        } else if (addr < HW_QUEUE_ENTRY) {
                ep_num = pdvobj->Queue2Pipe[addr];
                pipe = usb_sndbulkpipe(pusbd, ep_num);
index 78cab13bbb1be3796b0e00af4a0667329ed4a2d8..46588c85d39bd0ce206f213aebba9330db7e33b8 100644 (file)
@@ -1593,7 +1593,9 @@ int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
         * Initiator is expecting a NopIN ping reply..
         */
        if (hdr->itt != RESERVED_ITT) {
-               BUG_ON(!cmd);
+               if (!cmd)
+                       return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR,
+                                               (unsigned char *)hdr);
 
                spin_lock_bh(&conn->cmd_lock);
                list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
index 6960f22909ae2eeddd651d59217d1f09519e9154..302eb3b7871558bb2a1241fedc521e20efebf415 100644 (file)
@@ -775,6 +775,7 @@ struct iscsi_np {
        int                     np_ip_proto;
        int                     np_sock_type;
        enum np_thread_state_table np_thread_state;
+       bool                    enabled;
        enum iscsi_timer_flags_table np_login_timer_flags;
        u32                     np_exports;
        enum np_flags_table     np_flags;
index 8739b98f6f93539b8c6eb95f27d7fde3601b40d7..ca31fa1b8a4b69058290243bc61b0007d2c7d3cc 100644 (file)
@@ -436,7 +436,7 @@ static int iscsi_login_zero_tsih_s2(
                }
                off = mrdsl % PAGE_SIZE;
                if (!off)
-                       return 0;
+                       goto check_prot;
 
                if (mrdsl < PAGE_SIZE)
                        mrdsl = PAGE_SIZE;
@@ -452,6 +452,31 @@ static int iscsi_login_zero_tsih_s2(
                                ISCSI_LOGIN_STATUS_NO_RESOURCES);
                        return -1;
                }
+               /*
+                * ISER currently requires that ImmediateData + Unsolicited
+                * Data be disabled when protection / signature MRs are enabled.
+                */
+check_prot:
+               if (sess->se_sess->sup_prot_ops &
+                  (TARGET_PROT_DOUT_STRIP | TARGET_PROT_DOUT_PASS |
+                   TARGET_PROT_DOUT_INSERT)) {
+
+                       sprintf(buf, "ImmediateData=No");
+                       if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) {
+                               iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+                                                   ISCSI_LOGIN_STATUS_NO_RESOURCES);
+                               return -1;
+                       }
+
+                       sprintf(buf, "InitialR2T=Yes");
+                       if (iscsi_change_param_value(buf, conn->param_list, 0) < 0) {
+                               iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+                                                   ISCSI_LOGIN_STATUS_NO_RESOURCES);
+                               return -1;
+                       }
+                       pr_debug("Forcing ImmediateData=No + InitialR2T=Yes for"
+                                " T10-PI enabled ISER session\n");
+               }
        }
 
        return 0;
@@ -984,6 +1009,7 @@ int iscsi_target_setup_login_socket(
        }
 
        np->np_transport = t;
+       np->enabled = true;
        return 0;
 }
 
index eb96b20dc09e13ffe32e226df38b73241f176a63..ca1811858afd01fa4b09ba6e1523f32bd0c3e1b2 100644 (file)
@@ -184,6 +184,7 @@ static void iscsit_clear_tpg_np_login_thread(
                return;
        }
 
+       tpg_np->tpg_np->enabled = false;
        iscsit_reset_np_thread(tpg_np->tpg_np, tpg_np, tpg, shutdown);
 }
 
index 65001e1336702966108081443d5a44f39988d5af..26416c15d65c25c1b915f6bdf00b03db341b9152 100644 (file)
@@ -798,10 +798,10 @@ int se_dev_set_emulate_write_cache(struct se_device *dev, int flag)
                pr_err("emulate_write_cache not supported for pSCSI\n");
                return -EINVAL;
        }
-       if (dev->transport->get_write_cache) {
-               pr_warn("emulate_write_cache cannot be changed when underlying"
-                       " HW reports WriteCacheEnabled, ignoring request\n");
-               return 0;
+       if (flag &&
+           dev->transport->get_write_cache) {
+               pr_err("emulate_write_cache not supported for this device\n");
+               return -EINVAL;
        }
 
        dev->dev_attrib.emulate_write_cache = flag;
@@ -936,6 +936,10 @@ int se_dev_set_pi_prot_type(struct se_device *dev, int flag)
                return 0;
        }
        if (!dev->transport->init_prot || !dev->transport->free_prot) {
+               /* 0 is only allowed value for non-supporting backends */
+               if (flag == 0)
+                       return 0;
+
                pr_err("DIF protection not supported by backend: %s\n",
                       dev->transport->name);
                return -ENOSYS;
index d4b98690a73680244676b6e608ede6c85ff724cb..789aa9eb0a1e590b8853a49e8f0ae137f04d3241 100644 (file)
@@ -1113,6 +1113,7 @@ void transport_init_se_cmd(
        init_completion(&cmd->cmd_wait_comp);
        init_completion(&cmd->task_stop_comp);
        spin_lock_init(&cmd->t_state_lock);
+       kref_init(&cmd->cmd_kref);
        cmd->transport_state = CMD_T_DEV_ACTIVE;
 
        cmd->se_tfo = tfo;
@@ -2357,7 +2358,6 @@ int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
        unsigned long flags;
        int ret = 0;
 
-       kref_init(&se_cmd->cmd_kref);
        /*
         * Add a second kref if the fabric caller is expecting to handle
         * fabric acknowledgement that requires two target_put_sess_cmd()
index 01cf37f212c30724ed6a0addbe8c7cbe69dfd6a3..f5fd515b2bee266dd9c8279ea804bc7372d955f3 100644 (file)
@@ -90,18 +90,18 @@ static void ft_free_cmd(struct ft_cmd *cmd)
 {
        struct fc_frame *fp;
        struct fc_lport *lport;
-       struct se_session *se_sess;
+       struct ft_sess *sess;
 
        if (!cmd)
                return;
-       se_sess = cmd->sess->se_sess;
+       sess = cmd->sess;
        fp = cmd->req_frame;
        lport = fr_dev(fp);
        if (fr_seq(fp))
                lport->tt.seq_release(fr_seq(fp));
        fc_frame_free(fp);
-       percpu_ida_free(&se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
-       ft_sess_put(cmd->sess); /* undo get from lookup at recv */
+       percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
+       ft_sess_put(sess);      /* undo get from lookup at recv */
 }
 
 void ft_release_cmd(struct se_cmd *se_cmd)
index 94f9e3a38412f3071d63b4964925b375abec4283..0ff7fda0742f4326113cf82f8a72cb355c840319 100644 (file)
@@ -190,7 +190,7 @@ static struct tty_driver *hvc_console_device(struct console *c, int *index)
        return hvc_driver;
 }
 
-static int __init hvc_console_setup(struct console *co, char *options)
+static int hvc_console_setup(struct console *co, char *options)
 {      
        if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES)
                return -ENODEV;
index 41fe8a047d373cf84b14a9a2f5d8f41e07fd3b5f..fe9d129c87351b47392320a626dedb89e2f0bf55 100644 (file)
@@ -2353,8 +2353,12 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
                        if (tty->ops->flush_chars)
                                tty->ops->flush_chars(tty);
                } else {
+                       struct n_tty_data *ldata = tty->disc_data;
+
                        while (nr > 0) {
+                               mutex_lock(&ldata->output_lock);
                                c = tty->ops->write(tty, b, nr);
+                               mutex_unlock(&ldata->output_lock);
                                if (c < 0) {
                                        retval = c;
                                        goto break_out;
index 0e1bf88584311352767e646faedc2b39183932ce..2d4bd3929e507376f7d4b25f788fbba3b61af1a4 100644 (file)
@@ -555,7 +555,7 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
         */
        if ((p->port.type == PORT_XR17V35X) ||
           (p->port.type == PORT_XR17D15X)) {
-               serial_out(p, UART_EXAR_SLEEP, 0xff);
+               serial_out(p, UART_EXAR_SLEEP, sleep ? 0xff : 0);
                return;
        }
 
index f1d30f6945af2cf8fece1a5a1b40d59aa46cd5e0..cf78d1985cd851fb2b6615054bfabf5a8e3b2b13 100644 (file)
@@ -255,16 +255,15 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size,
        if (change || left < size) {
                /* This is the slow path - looking for new buffers to use */
                if ((n = tty_buffer_alloc(port, size)) != NULL) {
-                       unsigned long iflags;
-
                        n->flags = flags;
                        buf->tail = n;
-
-                       spin_lock_irqsave(&buf->flush_lock, iflags);
                        b->commit = b->used;
+                       /* paired w/ barrier in flush_to_ldisc(); ensures the
+                        * latest commit value can be read before the head is
+                        * advanced to the next buffer
+                        */
+                       smp_wmb();
                        b->next = n;
-                       spin_unlock_irqrestore(&buf->flush_lock, iflags);
-
                } else if (change)
                        size = 0;
                else
@@ -448,27 +447,28 @@ static void flush_to_ldisc(struct work_struct *work)
        mutex_lock(&buf->lock);
 
        while (1) {
-               unsigned long flags;
                struct tty_buffer *head = buf->head;
+               struct tty_buffer *next;
                int count;
 
                /* Ldisc or user is trying to gain exclusive access */
                if (atomic_read(&buf->priority))
                        break;
 
-               spin_lock_irqsave(&buf->flush_lock, flags);
+               next = head->next;
+               /* paired w/ barrier in __tty_buffer_request_room();
+                * ensures commit value read is not stale if the head
+                * is advancing to the next buffer
+                */
+               smp_rmb();
                count = head->commit - head->read;
                if (!count) {
-                       if (head->next == NULL) {
-                               spin_unlock_irqrestore(&buf->flush_lock, flags);
+                       if (next == NULL)
                                break;
-                       }
-                       buf->head = head->next;
-                       spin_unlock_irqrestore(&buf->flush_lock, flags);
+                       buf->head = next;
                        tty_buffer_free(port, head);
                        continue;
                }
-               spin_unlock_irqrestore(&buf->flush_lock, flags);
 
                count = receive_buf(tty, head, count);
                if (!count)
@@ -523,7 +523,6 @@ void tty_buffer_init(struct tty_port *port)
        struct tty_bufhead *buf = &port->buf;
 
        mutex_init(&buf->lock);
-       spin_lock_init(&buf->flush_lock);
        tty_buffer_reset(&buf->sentinel, 0);
        buf->head = &buf->sentinel;
        buf->tail = &buf->sentinel;
index f605ad8c1902fc775cffc39dcd53be8d65fe3a8f..cfd18bcca723ef700d727fa1f8f8a39405eba13f 100644 (file)
@@ -1709,16 +1709,6 @@ static int at91udc_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       if (pdev->num_resources != 2) {
-               DBG("invalid num_resources\n");
-               return -ENODEV;
-       }
-       if ((pdev->resource[0].flags != IORESOURCE_MEM)
-                       || (pdev->resource[1].flags != IORESOURCE_IRQ)) {
-               DBG("invalid resource type\n");
-               return -ENODEV;
-       }
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res)
                return -ENXIO;
index 6f2c8d3899d2cfb00f14fe641341f68944943213..cf2734b532a7ab288d24dd13fd79db364490a748 100644 (file)
@@ -248,7 +248,8 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
                break;
        }
 
-       if (pdata->have_sysif_regs && pdata->controller_ver &&
+       if (pdata->have_sysif_regs &&
+           pdata->controller_ver > FSL_USB_VER_1_6 &&
            (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) &
index c81c8721cc5a9e3d07e20c29d9d40e540136409e..cd871b89501325407af3ab3ebf0eb56ab0814a79 100644 (file)
@@ -90,6 +90,24 @@ __acquires(ohci->lock)
        dl_done_list (ohci);
        finish_unlinks (ohci, ohci_frame_no(ohci));
 
+       /*
+        * Some controllers don't handle "global" suspend properly if
+        * there are unsuspended ports.  For these controllers, put all
+        * the enabled ports into suspend before suspending the root hub.
+        */
+       if (ohci->flags & OHCI_QUIRK_GLOBAL_SUSPEND) {
+               __hc32 __iomem  *portstat = ohci->regs->roothub.portstatus;
+               int             i;
+               unsigned        temp;
+
+               for (i = 0; i < ohci->num_ports; (++i, ++portstat)) {
+                       temp = ohci_readl(ohci, portstat);
+                       if ((temp & (RH_PS_PES | RH_PS_PSS)) ==
+                                       RH_PS_PES)
+                               ohci_writel(ohci, RH_PS_PSS, portstat);
+               }
+       }
+
        /* maybe resume can wake root hub */
        if (ohci_to_hcd(ohci)->self.root_hub->do_remote_wakeup || autostop) {
                ohci->hc_control |= OHCI_CTRL_RWE;
index 90879e9ccbec302e8c5272d45e4847009b3730c4..bb1509675727b374586d61917920578cc7631a45 100644 (file)
@@ -160,6 +160,7 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
                ohci_dbg(ohci, "enabled AMD prefetch quirk\n");
        }
 
+       ohci->flags |= OHCI_QUIRK_GLOBAL_SUSPEND;
        return 0;
 }
 
index 9250cada13f0b3e9a22711de3345b67de1627e01..4550ce05af7fa1d1b96c03dc2590c5c0cc943615 100644 (file)
@@ -405,6 +405,8 @@ struct ohci_hcd {
 #define        OHCI_QUIRK_HUB_POWER    0x100                   /* distrust firmware power/oc setup */
 #define        OHCI_QUIRK_AMD_PLL      0x200                   /* AMD PLL quirk*/
 #define        OHCI_QUIRK_AMD_PREFETCH 0x400                   /* pre-fetch for ISO transfer */
+#define        OHCI_QUIRK_GLOBAL_SUSPEND       0x800           /* must suspend ports */
+
        // there are also chip quirks/bugs in init logic
 
        struct work_struct      nec_work;       /* Worker for NEC quirk */
index c47e5a6edde28a1d35d64d6f375df401a8519709..d03fadd2629f1419b00a60ef9d842913c5ae6183 100644 (file)
@@ -303,17 +303,18 @@ int otg_statemachine(struct otg_fsm *fsm)
                        otg_set_state(fsm, OTG_STATE_A_WAIT_VRISE);
                break;
        case OTG_STATE_A_WAIT_VRISE:
-               if (fsm->id || fsm->a_bus_drop || fsm->a_vbus_vld ||
-                               fsm->a_wait_vrise_tmout) {
+               if (fsm->a_vbus_vld)
                        otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
-               }
+               else if (fsm->id || fsm->a_bus_drop ||
+                               fsm->a_wait_vrise_tmout)
+                       otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
                break;
        case OTG_STATE_A_WAIT_BCON:
                if (!fsm->a_vbus_vld)
                        otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
                else if (fsm->b_conn)
                        otg_set_state(fsm, OTG_STATE_A_HOST);
-               else if (fsm->id | fsm->a_bus_drop | fsm->a_wait_bcon_tmout)
+               else if (fsm->id || fsm->a_bus_drop || fsm->a_wait_bcon_tmout)
                        otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
                break;
        case OTG_STATE_A_HOST:
index 7ed681a714a58864921bbd96edbfb1f02b92446c..6c0a542e8ec1820d60d03f5a7896843d4a6b96f6 100644 (file)
@@ -151,6 +151,21 @@ static const struct usb_device_id id_table[] = {
        {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9051, 0)},       /* Netgear AirCard 340U Device Management */
        {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9051, 2)},       /* Netgear AirCard 340U NMEA */
        {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x9051, 3)},       /* Netgear AirCard 340U Modem */
+       {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a2, 0)},       /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card Device Management */
+       {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a2, 2)},       /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card NMEA */
+       {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a2, 3)},       /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card Modem */
+       {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a3, 0)},       /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card Device Management */
+       {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a3, 2)},       /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card NMEA */
+       {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a3, 3)},       /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card Modem */
+       {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a4, 0)},       /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card Device Management */
+       {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a4, 2)},       /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card NMEA */
+       {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a4, 3)},       /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card Modem */
+       {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a8, 0)},       /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card Device Management */
+       {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a8, 2)},       /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card NMEA */
+       {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a8, 3)},       /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card Modem */
+       {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a9, 0)},       /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card Device Management */
+       {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a9, 2)},       /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card NMEA */
+       {USB_DEVICE_INTERFACE_NUMBER(0x413c, 0x81a9, 3)},       /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card Modem */
 
        { }                             /* Terminating entry */
 };
index 4ef2a80728f74521d103dc8d33b1fed8735b1947..008d805c3d21cde7458058a6a2a5b0803da92bcf 100644 (file)
@@ -1851,7 +1851,7 @@ static int usbat_probe(struct usb_interface *intf,
        us->transport_name = "Shuttle USBAT";
        us->transport = usbat_flash_transport;
        us->transport_reset = usb_stor_CB_reset;
-       us->max_lun = 1;
+       us->max_lun = 0;
 
        result = usb_stor_probe2(us);
        return result;
index f4a82291894ab2964754ac6eb06b1c7dfb4b3978..174a447868cd6924fd81f39ea0da8666b88e2110 100644 (file)
@@ -234,6 +234,20 @@ UNUSUAL_DEV(  0x0421, 0x0495, 0x0370, 0x0370,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_MAX_SECTORS_64 ),
 
+/* Reported by Daniele Forsi <dforsi@gmail.com> */
+UNUSUAL_DEV(  0x0421, 0x04b9, 0x0350, 0x0350,
+               "Nokia",
+               "5300",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_MAX_SECTORS_64 ),
+
+/* Patch submitted by Victor A. Santos <victoraur.santos@gmail.com> */
+UNUSUAL_DEV(  0x0421, 0x05af, 0x0742, 0x0742,
+               "Nokia",
+               "305",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_MAX_SECTORS_64),
+
 /* Patch submitted by Mikhail Zolotaryov <lebon@lebon.org.ua> */
 UNUSUAL_DEV(  0x0421, 0x06aa, 0x1110, 0x1110,
                "Nokia",
index e21d1f58554c6cc063eecf123043cfd713e71118..4953b657635e71a0e8267a8c89519157dd711ba9 100644 (file)
@@ -191,7 +191,7 @@ static struct fb_info fb_info = {
 };
 
 static void *screen_base;      /* base address of screen */
-static void *real_screen_base; /* (only for Overscan) */
+static unsigned long phys_screen_base; /* (only for Overscan) */
 
 static int screen_len;
 
@@ -213,7 +213,8 @@ static unsigned int external_yres;
  */
 static unsigned int external_depth;
 static int external_pmode;
-static void *external_addr;
+static void *external_screen_base;
+static unsigned long external_addr;
 static unsigned long external_len;
 static unsigned long external_vgaiobase;
 static unsigned int external_bitspercol = 6;
@@ -592,7 +593,7 @@ static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
        int mode;
 
        strcpy(fix->id, "Atari Builtin");
-       fix->smem_start = (unsigned long)real_screen_base;
+       fix->smem_start = phys_screen_base;
        fix->smem_len = screen_len;
        fix->type = FB_TYPE_INTERLEAVED_PLANES;
        fix->type_aux = 2;
@@ -790,7 +791,7 @@ static void tt_get_par(struct atafb_par *par)
        addr = ((shifter.bas_hi & 0xff) << 16) |
               ((shifter.bas_md & 0xff) << 8)  |
               ((shifter.bas_lo & 0xff));
-       par->screen_base = phys_to_virt(addr);
+       par->screen_base = atari_stram_to_virt(addr);
 }
 
 static void tt_set_par(struct atafb_par *par)
@@ -888,7 +889,7 @@ static int falcon_encode_fix(struct fb_fix_screeninfo *fix,
                             struct atafb_par *par)
 {
        strcpy(fix->id, "Atari Builtin");
-       fix->smem_start = (unsigned long)real_screen_base;
+       fix->smem_start = phys_screen_base;
        fix->smem_len = screen_len;
        fix->type = FB_TYPE_INTERLEAVED_PLANES;
        fix->type_aux = 2;
@@ -1584,7 +1585,7 @@ static void falcon_get_par(struct atafb_par *par)
        addr = (shifter.bas_hi & 0xff) << 16 |
               (shifter.bas_md & 0xff) << 8  |
               (shifter.bas_lo & 0xff);
-       par->screen_base = phys_to_virt(addr);
+       par->screen_base = atari_stram_to_virt(addr);
 
        /* derived parameters */
        hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100;
@@ -1814,7 +1815,7 @@ static int stste_encode_fix(struct fb_fix_screeninfo *fix,
        int mode;
 
        strcpy(fix->id, "Atari Builtin");
-       fix->smem_start = (unsigned long)real_screen_base;
+       fix->smem_start = phys_screen_base;
        fix->smem_len = screen_len;
        fix->type = FB_TYPE_INTERLEAVED_PLANES;
        fix->type_aux = 2;
@@ -1980,7 +1981,7 @@ static void stste_get_par(struct atafb_par *par)
               ((shifter.bas_md & 0xff) << 8);
        if (ATARIHW_PRESENT(EXTD_SHIFTER))
                addr |= (shifter.bas_lo & 0xff);
-       par->screen_base = phys_to_virt(addr);
+       par->screen_base = atari_stram_to_virt(addr);
 }
 
 static void stste_set_par(struct atafb_par *par)
@@ -2039,7 +2040,7 @@ static int stste_detect(void)
 static void stste_set_screen_base(void *s_base)
 {
        unsigned long addr;
-       addr = virt_to_phys(s_base);
+       addr = atari_stram_to_phys(s_base);
        /* Setup Screen Memory */
        shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
        shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
@@ -2113,7 +2114,7 @@ static void st_ovsc_switch(void)
 static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
 {
        strcpy(fix->id, "Unknown Extern");
-       fix->smem_start = (unsigned long)external_addr;
+       fix->smem_start = external_addr;
        fix->smem_len = PAGE_ALIGN(external_len);
        if (external_depth == 1) {
                fix->type = FB_TYPE_PACKED_PIXELS;
@@ -2213,7 +2214,7 @@ static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
 
 static void ext_get_par(struct atafb_par *par)
 {
-       par->screen_base = external_addr;
+       par->screen_base = external_screen_base;
 }
 
 static void ext_set_par(struct atafb_par *par)
@@ -2286,7 +2287,7 @@ static void set_screen_base(void *s_base)
 {
        unsigned long addr;
 
-       addr = virt_to_phys(s_base);
+       addr = atari_stram_to_phys(s_base);
        /* Setup Screen Memory */
        shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16);
        shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8);
@@ -2433,7 +2434,9 @@ static void atafb_set_disp(struct fb_info *info)
        atafb_get_var(&info->var, info);
        atafb_get_fix(&info->fix, info);
 
-       info->screen_base = (void *)info->fix.smem_start;
+       /* Note: smem_start derives from phys_screen_base, not screen_base! */
+       info->screen_base = (external_addr ? external_screen_base :
+                               atari_stram_to_virt(info->fix.smem_start));
 }
 
 static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
@@ -2904,7 +2907,7 @@ static void __init atafb_setup_ext(char *spec)
        external_yres = yres;
        external_depth = depth;
        external_pmode = planes;
-       external_addr = (void *)addr;
+       external_addr = addr;
        external_len = len;
 
        if (external_card_type == IS_MV300) {
@@ -3166,30 +3169,30 @@ int __init atafb_init(void)
                memset(screen_base, 0, mem_req);
                pad = -(unsigned long)screen_base & (PAGE_SIZE - 1);
                screen_base += pad;
-               real_screen_base = screen_base + ovsc_offset;
+               phys_screen_base = atari_stram_to_phys(screen_base + ovsc_offset);
                screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
                st_ovsc_switch();
                if (CPU_IS_040_OR_060) {
                        /* On a '040+, the cache mode of video RAM must be set to
                         * write-through also for internal video hardware! */
-                       cache_push(virt_to_phys(screen_base), screen_len);
+                       cache_push(atari_stram_to_phys(screen_base), screen_len);
                        kernel_set_cachemode(screen_base, screen_len,
                                             IOMAP_WRITETHROUGH);
                }
-               printk("atafb: screen_base %p real_screen_base %p screen_len %d\n",
-                       screen_base, real_screen_base, screen_len);
+               printk("atafb: screen_base %p phys_screen_base %lx screen_len %d\n",
+                       screen_base, phys_screen_base, screen_len);
 #ifdef ATAFB_EXT
        } else {
                /* Map the video memory (physical address given) to somewhere
                 * in the kernel address space.
                 */
-               external_addr = ioremap_writethrough((unsigned long)external_addr,
+               external_screen_base = ioremap_writethrough(external_addr,
                                                     external_len);
                if (external_vgaiobase)
                        external_vgaiobase =
                          (unsigned long)ioremap(external_vgaiobase, 0x10000);
-               screen_base =
-               real_screen_base = external_addr;
+               screen_base = external_screen_base;
+               phys_screen_base = external_addr;
                screen_len = external_len & PAGE_MASK;
                memset (screen_base, 0, external_len);
        }
@@ -3235,8 +3238,8 @@ int __init atafb_init(void)
        if (register_framebuffer(&fb_info) < 0) {
 #ifdef ATAFB_EXT
                if (external_addr) {
-                       iounmap(external_addr);
-                       external_addr = NULL;
+                       iounmap(external_screen_base);
+                       external_addr = 0;
                }
                if (external_vgaiobase) {
                        iounmap((void*)external_vgaiobase);
index 96109a9972b6113cdb88d1861bf00353a00a0a93..84b4bfb843443ef934d2d80abc12131bb8616a5a 100644 (file)
@@ -66,7 +66,22 @@ static DEFINE_PER_CPU(struct evtchn_fifo_queue, cpu_queue);
 static event_word_t *event_array[MAX_EVENT_ARRAY_PAGES] __read_mostly;
 static unsigned event_array_pages __read_mostly;
 
+/*
+ * sync_set_bit() and friends must be unsigned long aligned on non-x86
+ * platforms.
+ */
+#if !defined(CONFIG_X86) && BITS_PER_LONG > 32
+
+#define BM(w) (unsigned long *)((unsigned long)w & ~0x7UL)
+#define EVTCHN_FIFO_BIT(b, w) \
+    (((unsigned long)w & 0x4UL) ? (EVTCHN_FIFO_ ##b + 32) : EVTCHN_FIFO_ ##b)
+
+#else
+
 #define BM(w) ((unsigned long *)(w))
+#define EVTCHN_FIFO_BIT(b, w) EVTCHN_FIFO_ ##b
+
+#endif
 
 static inline event_word_t *event_word_from_port(unsigned port)
 {
@@ -161,33 +176,38 @@ static void evtchn_fifo_bind_to_cpu(struct irq_info *info, unsigned cpu)
 static void evtchn_fifo_clear_pending(unsigned port)
 {
        event_word_t *word = event_word_from_port(port);
-       sync_clear_bit(EVTCHN_FIFO_PENDING, BM(word));
+       sync_clear_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word));
 }
 
 static void evtchn_fifo_set_pending(unsigned port)
 {
        event_word_t *word = event_word_from_port(port);
-       sync_set_bit(EVTCHN_FIFO_PENDING, BM(word));
+       sync_set_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word));
 }
 
 static bool evtchn_fifo_is_pending(unsigned port)
 {
        event_word_t *word = event_word_from_port(port);
-       return sync_test_bit(EVTCHN_FIFO_PENDING, BM(word));
+       return sync_test_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word));
 }
 
 static bool evtchn_fifo_test_and_set_mask(unsigned port)
 {
        event_word_t *word = event_word_from_port(port);
-       return sync_test_and_set_bit(EVTCHN_FIFO_MASKED, BM(word));
+       return sync_test_and_set_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word));
 }
 
 static void evtchn_fifo_mask(unsigned port)
 {
        event_word_t *word = event_word_from_port(port);
-       sync_set_bit(EVTCHN_FIFO_MASKED, BM(word));
+       sync_set_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word));
 }
 
+static bool evtchn_fifo_is_masked(unsigned port)
+{
+       event_word_t *word = event_word_from_port(port);
+       return sync_test_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word));
+}
 /*
  * Clear MASKED, spinning if BUSY is set.
  */
@@ -211,7 +231,7 @@ static void evtchn_fifo_unmask(unsigned port)
        BUG_ON(!irqs_disabled());
 
        clear_masked(word);
-       if (sync_test_bit(EVTCHN_FIFO_PENDING, BM(word))) {
+       if (evtchn_fifo_is_pending(port)) {
                struct evtchn_unmask unmask = { .port = port };
                (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask);
        }
@@ -243,7 +263,7 @@ static void handle_irq_for_port(unsigned port)
 
 static void consume_one_event(unsigned cpu,
                              struct evtchn_fifo_control_block *control_block,
-                             unsigned priority, uint32_t *ready)
+                             unsigned priority, unsigned long *ready)
 {
        struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu);
        uint32_t head;
@@ -273,10 +293,9 @@ static void consume_one_event(unsigned cpu,
         * copy of the ready word.
         */
        if (head == 0)
-               clear_bit(priority, BM(ready));
+               clear_bit(priority, ready);
 
-       if (sync_test_bit(EVTCHN_FIFO_PENDING, BM(word))
-           && !sync_test_bit(EVTCHN_FIFO_MASKED, BM(word)))
+       if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port))
                handle_irq_for_port(port);
 
        q->head[priority] = head;
@@ -285,7 +304,7 @@ static void consume_one_event(unsigned cpu,
 static void evtchn_fifo_handle_events(unsigned cpu)
 {
        struct evtchn_fifo_control_block *control_block;
-       uint32_t ready;
+       unsigned long ready;
        unsigned q;
 
        control_block = per_cpu(cpu_control_block, cpu);
index 32f9236c959fd30d2ca505fe0478f806d7940e40..c3667b202f2f50618d85d147d86ac746535e3464 100644 (file)
@@ -41,9 +41,6 @@ static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
 
 struct suspend_info {
        int cancelled;
-       unsigned long arg; /* extra hypercall argument */
-       void (*pre)(void);
-       void (*post)(int cancelled);
 };
 
 static RAW_NOTIFIER_HEAD(xen_resume_notifier);
@@ -61,26 +58,6 @@ void xen_resume_notifier_unregister(struct notifier_block *nb)
 EXPORT_SYMBOL_GPL(xen_resume_notifier_unregister);
 
 #ifdef CONFIG_HIBERNATE_CALLBACKS
-static void xen_hvm_post_suspend(int cancelled)
-{
-       xen_arch_hvm_post_suspend(cancelled);
-       gnttab_resume();
-}
-
-static void xen_pre_suspend(void)
-{
-       xen_mm_pin_all();
-       gnttab_suspend();
-       xen_arch_pre_suspend();
-}
-
-static void xen_post_suspend(int cancelled)
-{
-       xen_arch_post_suspend(cancelled);
-       gnttab_resume();
-       xen_mm_unpin_all();
-}
-
 static int xen_suspend(void *data)
 {
        struct suspend_info *si = data;
@@ -94,18 +71,20 @@ static int xen_suspend(void *data)
                return err;
        }
 
-       if (si->pre)
-               si->pre();
+       gnttab_suspend();
+       xen_arch_pre_suspend();
 
        /*
         * This hypercall returns 1 if suspend was cancelled
         * or the domain was merely checkpointed, and 0 if it
         * is resuming in a new domain.
         */
-       si->cancelled = HYPERVISOR_suspend(si->arg);
+       si->cancelled = HYPERVISOR_suspend(xen_pv_domain()
+                                           ? virt_to_mfn(xen_start_info)
+                                           : 0);
 
-       if (si->post)
-               si->post(si->cancelled);
+       xen_arch_post_suspend(si->cancelled);
+       gnttab_resume();
 
        if (!si->cancelled) {
                xen_irq_resume();
@@ -154,16 +133,6 @@ static void do_suspend(void)
 
        si.cancelled = 1;
 
-       if (xen_hvm_domain()) {
-               si.arg = 0UL;
-               si.pre = NULL;
-               si.post = &xen_hvm_post_suspend;
-       } else {
-               si.arg = virt_to_mfn(xen_start_info);
-               si.pre = &xen_pre_suspend;
-               si.post = &xen_post_suspend;
-       }
-
        err = stop_machine(xen_suspend, &si, cpumask_of(0));
 
        raw_notifier_call_chain(&xen_resume_notifier, 0, NULL);
index 82358d14ecf18a020f200aa0dc8260d9a6d1807b..59fc190f1e927da2edc58a536557adac9ce73a8f 100644 (file)
@@ -127,7 +127,7 @@ static int push_cxx_to_hypervisor(struct acpi_processor *_pr)
                        pr_debug("     C%d: %s %d uS\n",
                                 cx->type, cx->desc, (u32)cx->latency);
                }
-       } else if (ret != -EINVAL)
+       } else if ((ret != -EINVAL) && (ret != -ENOSYS))
                /* EINVAL means the ACPI ID is incorrect - meaning the ACPI
                 * table is referencing a non-existing CPU - which can happen
                 * with broken ACPI tables. */
@@ -259,7 +259,7 @@ static int push_pxx_to_hypervisor(struct acpi_processor *_pr)
                        (u32) perf->states[i].power,
                        (u32) perf->states[i].transition_latency);
                }
-       } else if (ret != -EINVAL)
+       } else if ((ret != -EINVAL) && (ret != -ENOSYS))
                /* EINVAL means the ACPI ID is incorrect - meaning the ACPI
                 * table is referencing a non-existing CPU - which can happen
                 * with broken ACPI tables. */
index 62fcd485f0a76e37fe9d07bd62e6a3d367704cfa..d57a173685f3bddf4ff2ec42feaa5a1ed35af06e 100644 (file)
@@ -242,6 +242,15 @@ struct pci_dev *pcistub_get_pci_dev(struct xen_pcibk_device *pdev,
        return found_dev;
 }
 
+/*
+ * Called when:
+ *  - XenBus state has been reconfigure (pci unplug). See xen_pcibk_remove_device
+ *  - XenBus state has been disconnected (guest shutdown). See xen_pcibk_xenbus_remove
+ *  - 'echo BDF > unbind' on pciback module with no guest attached. See pcistub_remove
+ *  - 'echo BDF > unbind' with a guest still using it. See pcistub_remove
+ *
+ *  As such we have to be careful.
+ */
 void pcistub_put_pci_dev(struct pci_dev *dev)
 {
        struct pcistub_device *psdev, *found_psdev = NULL;
@@ -272,16 +281,16 @@ void pcistub_put_pci_dev(struct pci_dev *dev)
         * and want to inhibit the user from fiddling with 'reset'
         */
        pci_reset_function(dev);
-       pci_restore_state(psdev->dev);
+       pci_restore_state(dev);
 
        /* This disables the device. */
-       xen_pcibk_reset_device(found_psdev->dev);
+       xen_pcibk_reset_device(dev);
 
        /* And cleanup up our emulated fields. */
-       xen_pcibk_config_free_dyn_fields(found_psdev->dev);
-       xen_pcibk_config_reset_dev(found_psdev->dev);
+       xen_pcibk_config_reset_dev(dev);
+       xen_pcibk_config_free_dyn_fields(dev);
 
-       xen_unregister_device_domain_owner(found_psdev->dev);
+       xen_unregister_device_domain_owner(dev);
 
        spin_lock_irqsave(&found_psdev->lock, flags);
        found_psdev->pdev = NULL;
@@ -493,6 +502,8 @@ static int pcistub_seize(struct pci_dev *dev)
        return err;
 }
 
+/* Called when 'bind'. This means we must _NOT_ call pci_reset_function or
+ * other functions that take the sysfs lock. */
 static int pcistub_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        int err = 0;
@@ -520,6 +531,8 @@ out:
        return err;
 }
 
+/* Called when 'unbind'. This means we must _NOT_ call pci_reset_function or
+ * other functions that take the sysfs lock. */
 static void pcistub_remove(struct pci_dev *dev)
 {
        struct pcistub_device *psdev, *found_psdev = NULL;
@@ -551,6 +564,8 @@ static void pcistub_remove(struct pci_dev *dev)
                        pr_warn("****** shutdown driver domain before binding device\n");
                        pr_warn("****** to other drivers or domains\n");
 
+                       /* N.B. This ends up calling pcistub_put_pci_dev which ends up
+                        * doing the FLR. */
                        xen_pcibk_release_pci_dev(found_psdev->pdev,
                                                found_psdev->dev);
                }
index a9ed867afaba5408a3949ca7f4808aebf2b5bab9..4a7e6e0a5f4c602ad280ffe5b258bd5fc44ed5f9 100644 (file)
@@ -93,6 +93,8 @@ static void free_pdev(struct xen_pcibk_device *pdev)
 
        xen_pcibk_disconnect(pdev);
 
+       /* N.B. This calls pcistub_put_pci_dev which does the FLR on all
+        * of the PCIe devices. */
        xen_pcibk_release_devices(pdev);
 
        dev_set_drvdata(&pdev->xdev->dev, NULL);
@@ -286,6 +288,8 @@ static int xen_pcibk_remove_device(struct xen_pcibk_device *pdev,
        dev_dbg(&dev->dev, "unregistering for %d\n", pdev->xdev->otherend_id);
        xen_unregister_device_domain_owner(dev);
 
+       /* N.B. This ends up calling pcistub_put_pci_dev which ends up
+        * doing the FLR. */
        xen_pcibk_release_pci_dev(pdev, dev);
 
 out:
index 6d589f28bf9b849bae629cea4d61f7dba60eda2d..895ac7dc9dbf9ef1ab800b713373887ebc17f903 100644 (file)
@@ -340,8 +340,6 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
                                &blocksize,&sbi->s_prefix,
                                sbi->s_volume, &mount_flags)) {
                printk(KERN_ERR "AFFS: Error parsing options\n");
-               kfree(sbi->s_prefix);
-               kfree(sbi);
                return -EINVAL;
        }
        /* N.B. after this point s_prefix must be released */
index 1c8c6cc6de3097ceab15a5a16307e0b569ee6a29..4b0eff6da6740552043679764f0ebc76a47917a0 100644 (file)
@@ -130,6 +130,15 @@ static void afs_cm_destructor(struct afs_call *call)
 {
        _enter("");
 
+       /* Break the callbacks here so that we do it after the final ACK is
+        * received.  The step number here must match the final number in
+        * afs_deliver_cb_callback().
+        */
+       if (call->unmarshall == 6) {
+               ASSERT(call->server && call->count && call->request);
+               afs_break_callbacks(call->server, call->count, call->request);
+       }
+
        afs_put_server(call->server);
        call->server = NULL;
        kfree(call->buffer);
@@ -272,6 +281,16 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
                _debug("trailer");
                if (skb->len != 0)
                        return -EBADMSG;
+
+               /* Record that the message was unmarshalled successfully so
+                * that the call destructor can know do the callback breaking
+                * work, even if the final ACK isn't received.
+                *
+                * If the step number changes, then afs_cm_destructor() must be
+                * updated also.
+                */
+               call->unmarshall++;
+       case 6:
                break;
        }
 
index be75b500005d0d4f68b2d6e3855e71660016353d..590b55f46d61dd1ca169ff78a3dbf4f5d32b813c 100644 (file)
@@ -75,7 +75,7 @@ struct afs_call {
        const struct afs_call_type *type;       /* type of call */
        const struct afs_wait_mode *wait_mode;  /* completion wait mode */
        wait_queue_head_t       waitq;          /* processes awaiting completion */
-       work_func_t             async_workfn;
+       void (*async_workfn)(struct afs_call *call); /* asynchronous work function */
        struct work_struct      async_work;     /* asynchronous work processor */
        struct work_struct      work;           /* actual work processor */
        struct sk_buff_head     rx_queue;       /* received packets */
index ef943df73b8cdee2c6964439b81417a9c1110b12..03a3beb170048df40c436dff51c41373104cf9e7 100644 (file)
@@ -25,7 +25,7 @@ static void afs_wake_up_call_waiter(struct afs_call *);
 static int afs_wait_for_call_to_complete(struct afs_call *);
 static void afs_wake_up_async_call(struct afs_call *);
 static int afs_dont_wait_for_call_to_complete(struct afs_call *);
-static void afs_process_async_call(struct work_struct *);
+static void afs_process_async_call(struct afs_call *);
 static void afs_rx_interceptor(struct sock *, unsigned long, struct sk_buff *);
 static int afs_deliver_cm_op_id(struct afs_call *, struct sk_buff *, bool);
 
@@ -58,6 +58,13 @@ static void afs_collect_incoming_call(struct work_struct *);
 static struct sk_buff_head afs_incoming_calls;
 static DECLARE_WORK(afs_collect_incoming_call_work, afs_collect_incoming_call);
 
+static void afs_async_workfn(struct work_struct *work)
+{
+       struct afs_call *call = container_of(work, struct afs_call, async_work);
+
+       call->async_workfn(call);
+}
+
 /*
  * open an RxRPC socket and bind it to be a server for callback notifications
  * - the socket is left in blocking mode and non-blocking ops use MSG_DONTWAIT
@@ -183,6 +190,28 @@ static void afs_free_call(struct afs_call *call)
        kfree(call);
 }
 
+/*
+ * End a call but do not free it
+ */
+static void afs_end_call_nofree(struct afs_call *call)
+{
+       if (call->rxcall) {
+               rxrpc_kernel_end_call(call->rxcall);
+               call->rxcall = NULL;
+       }
+       if (call->type->destructor)
+               call->type->destructor(call);
+}
+
+/*
+ * End a call and free it
+ */
+static void afs_end_call(struct afs_call *call)
+{
+       afs_end_call_nofree(call);
+       afs_free_call(call);
+}
+
 /*
  * allocate a call with flat request and reply buffers
  */
@@ -326,7 +355,8 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
               atomic_read(&afs_outstanding_calls));
 
        call->wait_mode = wait_mode;
-       INIT_WORK(&call->async_work, afs_process_async_call);
+       call->async_workfn = afs_process_async_call;
+       INIT_WORK(&call->async_work, afs_async_workfn);
 
        memset(&srx, 0, sizeof(srx));
        srx.srx_family = AF_RXRPC;
@@ -383,11 +413,8 @@ error_do_abort:
        rxrpc_kernel_abort_call(rxcall, RX_USER_ABORT);
        while ((skb = skb_dequeue(&call->rx_queue)))
                afs_free_skb(skb);
-       rxrpc_kernel_end_call(rxcall);
-       call->rxcall = NULL;
 error_kill_call:
-       call->type->destructor(call);
-       afs_free_call(call);
+       afs_end_call(call);
        _leave(" = %d", ret);
        return ret;
 }
@@ -509,12 +536,8 @@ static void afs_deliver_to_call(struct afs_call *call)
        if (call->state >= AFS_CALL_COMPLETE) {
                while ((skb = skb_dequeue(&call->rx_queue)))
                        afs_free_skb(skb);
-               if (call->incoming) {
-                       rxrpc_kernel_end_call(call->rxcall);
-                       call->rxcall = NULL;
-                       call->type->destructor(call);
-                       afs_free_call(call);
-               }
+               if (call->incoming)
+                       afs_end_call(call);
        }
 
        _leave("");
@@ -564,10 +587,7 @@ static int afs_wait_for_call_to_complete(struct afs_call *call)
        }
 
        _debug("call complete");
-       rxrpc_kernel_end_call(call->rxcall);
-       call->rxcall = NULL;
-       call->type->destructor(call);
-       afs_free_call(call);
+       afs_end_call(call);
        _leave(" = %d", ret);
        return ret;
 }
@@ -603,11 +623,8 @@ static int afs_dont_wait_for_call_to_complete(struct afs_call *call)
 /*
  * delete an asynchronous call
  */
-static void afs_delete_async_call(struct work_struct *work)
+static void afs_delete_async_call(struct afs_call *call)
 {
-       struct afs_call *call =
-               container_of(work, struct afs_call, async_work);
-
        _enter("");
 
        afs_free_call(call);
@@ -620,11 +637,8 @@ static void afs_delete_async_call(struct work_struct *work)
  * - on a multiple-thread workqueue this work item may try to run on several
  *   CPUs at the same time
  */
-static void afs_process_async_call(struct work_struct *work)
+static void afs_process_async_call(struct afs_call *call)
 {
-       struct afs_call *call =
-               container_of(work, struct afs_call, async_work);
-
        _enter("");
 
        if (!skb_queue_empty(&call->rx_queue))
@@ -637,10 +651,7 @@ static void afs_process_async_call(struct work_struct *work)
                call->reply = NULL;
 
                /* kill the call */
-               rxrpc_kernel_end_call(call->rxcall);
-               call->rxcall = NULL;
-               if (call->type->destructor)
-                       call->type->destructor(call);
+               afs_end_call_nofree(call);
 
                /* we can't just delete the call because the work item may be
                 * queued */
@@ -663,13 +674,6 @@ void afs_transfer_reply(struct afs_call *call, struct sk_buff *skb)
        call->reply_size += len;
 }
 
-static void afs_async_workfn(struct work_struct *work)
-{
-       struct afs_call *call = container_of(work, struct afs_call, async_work);
-
-       call->async_workfn(work);
-}
-
 /*
  * accept the backlog of incoming calls
  */
@@ -790,10 +794,7 @@ void afs_send_empty_reply(struct afs_call *call)
                _debug("oom");
                rxrpc_kernel_abort_call(call->rxcall, RX_USER_ABORT);
        default:
-               rxrpc_kernel_end_call(call->rxcall);
-               call->rxcall = NULL;
-               call->type->destructor(call);
-               afs_free_call(call);
+               afs_end_call(call);
                _leave(" [error]");
                return;
        }
@@ -823,17 +824,16 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
        call->state = AFS_CALL_AWAIT_ACK;
        n = rxrpc_kernel_send_data(call->rxcall, &msg, len);
        if (n >= 0) {
+               /* Success */
                _leave(" [replied]");
                return;
        }
+
        if (n == -ENOMEM) {
                _debug("oom");
                rxrpc_kernel_abort_call(call->rxcall, RX_USER_ABORT);
        }
-       rxrpc_kernel_end_call(call->rxcall);
-       call->rxcall = NULL;
-       call->type->destructor(call);
-       afs_free_call(call);
+       afs_end_call(call);
        _leave(" [error]");
 }
 
index 2caf36ac3e93e41d4f14ac48ef4bcedc4b682548..cc87c1abac9710169cd56ad44a78cf7185da2834 100644 (file)
@@ -179,7 +179,7 @@ static struct dentry *autofs4_lookup_active(struct dentry *dentry)
                spin_lock(&active->d_lock);
 
                /* Already gone? */
-               if (!d_count(active))
+               if ((int) d_count(active) <= 0)
                        goto next;
 
                qstr = &active->d_name;
@@ -230,7 +230,7 @@ static struct dentry *autofs4_lookup_expiring(struct dentry *dentry)
 
                spin_lock(&expiring->d_lock);
 
-               /* Bad luck, we've already been dentry_iput */
+               /* We've already been dentry_iput or unlinked */
                if (!expiring->d_inode)
                        goto next;
 
index 2ad7de94efef71e58af4e747cd05d3cb3aeeba40..2f6d7b13b5bdacaba4df505b57b1c3cd9417ee13 100644 (file)
@@ -3120,6 +3120,8 @@ process_slot:
                        } else if (type == BTRFS_FILE_EXTENT_INLINE) {
                                u64 skip = 0;
                                u64 trim = 0;
+                               u64 aligned_end = 0;
+
                                if (off > key.offset) {
                                        skip = off - key.offset;
                                        new_key.offset += skip;
@@ -3136,9 +3138,11 @@ process_slot:
                                size -= skip + trim;
                                datal -= skip + trim;
 
+                               aligned_end = ALIGN(new_key.offset + datal,
+                                                   root->sectorsize);
                                ret = btrfs_drop_extents(trans, root, inode,
                                                         new_key.offset,
-                                                        new_key.offset + datal,
+                                                        aligned_end,
                                                         1);
                                if (ret) {
                                        if (ret != -EOPNOTSUPP)
index eb6537a08c1bf4438f0bc90df319977cb964bee7..fd38b5053479cf62f3297d43038288027646ebe0 100644 (file)
@@ -1668,7 +1668,7 @@ static int get_first_ref(struct btrfs_root *root, u64 ino,
                goto out;
        }
 
-       if (key.type == BTRFS_INODE_REF_KEY) {
+       if (found_key.type == BTRFS_INODE_REF_KEY) {
                struct btrfs_inode_ref *iref;
                iref = btrfs_item_ptr(path->nodes[0], path->slots[0],
                                      struct btrfs_inode_ref);
index 2e5e648eb5c3dc3bd82bea5ce8dead051864cf75..c561b628ebce519d111d159f541b9df88242a5b1 100644 (file)
@@ -3261,7 +3261,7 @@ int ceph_encode_inode_release(void **p, struct inode *inode,
                        rel->seq = cpu_to_le32(cap->seq);
                        rel->issue_seq = cpu_to_le32(cap->issue_seq),
                        rel->mseq = cpu_to_le32(cap->mseq);
-                       rel->caps = cpu_to_le32(cap->issued);
+                       rel->caps = cpu_to_le32(cap->implemented);
                        rel->wanted = cpu_to_le32(cap->mds_wanted);
                        rel->dname_len = 0;
                        rel->dname_seq = 0;
index 766410a12c2cb209a224fcfd97f63a055fd20801..c29d6ae6887489c29902bec33c4118d4d807e9dc 100644 (file)
@@ -141,7 +141,7 @@ static int __dcache_readdir(struct file *file,  struct dir_context *ctx,
 
        /* start at beginning? */
        if (ctx->pos == 2 || last == NULL ||
-           ctx->pos < ceph_dentry(last)->offset) {
+           fpos_cmp(ctx->pos, ceph_dentry(last)->offset) < 0) {
                if (list_empty(&parent->d_subdirs))
                        goto out_unlock;
                p = parent->d_subdirs.prev;
@@ -182,9 +182,16 @@ more:
        spin_unlock(&dentry->d_lock);
        spin_unlock(&parent->d_lock);
 
+       /* make sure a dentry wasn't dropped while we didn't have parent lock */
+       if (!ceph_dir_is_complete(dir)) {
+               dout(" lost dir complete on %p; falling back to mds\n", dir);
+               dput(dentry);
+               err = -EAGAIN;
+               goto out;
+       }
+
        dout(" %llu (%llu) dentry %p %.*s %p\n", di->offset, ctx->pos,
             dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode);
-       ctx->pos = di->offset;
        if (!dir_emit(ctx, dentry->d_name.name,
                      dentry->d_name.len,
                      ceph_translate_ino(dentry->d_sb, dentry->d_inode->i_ino),
@@ -198,19 +205,12 @@ more:
                return 0;
        }
 
+       ctx->pos = di->offset + 1;
+
        if (last)
                dput(last);
        last = dentry;
 
-       ctx->pos++;
-
-       /* make sure a dentry wasn't dropped while we didn't have parent lock */
-       if (!ceph_dir_is_complete(dir)) {
-               dout(" lost dir complete on %p; falling back to mds\n", dir);
-               err = -EAGAIN;
-               goto out;
-       }
-
        spin_lock(&parent->d_lock);
        p = p->prev;    /* advance to next dentry */
        goto more;
@@ -296,6 +296,8 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
                err = __dcache_readdir(file, ctx, shared_gen);
                if (err != -EAGAIN)
                        return err;
+               frag = fpos_frag(ctx->pos);
+               off = fpos_off(ctx->pos);
        } else {
                spin_unlock(&ci->i_ceph_lock);
        }
@@ -446,7 +448,6 @@ more:
        if (atomic_read(&ci->i_release_count) == fi->dir_release_count) {
                dout(" marking %p complete\n", inode);
                __ceph_dir_set_complete(ci, fi->dir_release_count);
-               ci->i_max_offset = ctx->pos;
        }
        spin_unlock(&ci->i_ceph_lock);
 
@@ -935,14 +936,16 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry,
                 * to do it here.
                 */
 
-               /* d_move screws up d_subdirs order */
-               ceph_dir_clear_complete(new_dir);
-
                d_move(old_dentry, new_dentry);
 
                /* ensure target dentry is invalidated, despite
                   rehashing bug in vfs_rename_dir */
                ceph_invalidate_dentry_lease(new_dentry);
+
+               /* d_move screws up sibling dentries' offsets */
+               ceph_dir_clear_complete(old_dir);
+               ceph_dir_clear_complete(new_dir);
+
        }
        ceph_mdsc_put_request(req);
        return err;
index 0b0728e5be2d7cba589a935159b88f9d26f0b2e9..233c6f96910abc78d2b120e4e30a44ba0009b88a 100644 (file)
@@ -744,7 +744,6 @@ static int fill_inode(struct inode *inode,
            !__ceph_dir_is_complete(ci)) {
                dout(" marking %p complete (empty)\n", inode);
                __ceph_dir_set_complete(ci, atomic_read(&ci->i_release_count));
-               ci->i_max_offset = 2;
        }
 no_change:
        /* only update max_size on auth cap */
@@ -889,41 +888,6 @@ out_unlock:
        return;
 }
 
-/*
- * Set dentry's directory position based on the current dir's max, and
- * order it in d_subdirs, so that dcache_readdir behaves.
- *
- * Always called under directory's i_mutex.
- */
-static void ceph_set_dentry_offset(struct dentry *dn)
-{
-       struct dentry *dir = dn->d_parent;
-       struct inode *inode = dir->d_inode;
-       struct ceph_inode_info *ci;
-       struct ceph_dentry_info *di;
-
-       BUG_ON(!inode);
-
-       ci = ceph_inode(inode);
-       di = ceph_dentry(dn);
-
-       spin_lock(&ci->i_ceph_lock);
-       if (!__ceph_dir_is_complete(ci)) {
-               spin_unlock(&ci->i_ceph_lock);
-               return;
-       }
-       di->offset = ceph_inode(inode)->i_max_offset++;
-       spin_unlock(&ci->i_ceph_lock);
-
-       spin_lock(&dir->d_lock);
-       spin_lock_nested(&dn->d_lock, DENTRY_D_LOCK_NESTED);
-       list_move(&dn->d_u.d_child, &dir->d_subdirs);
-       dout("set_dentry_offset %p %lld (%p %p)\n", dn, di->offset,
-            dn->d_u.d_child.prev, dn->d_u.d_child.next);
-       spin_unlock(&dn->d_lock);
-       spin_unlock(&dir->d_lock);
-}
-
 /*
  * splice a dentry to an inode.
  * caller must hold directory i_mutex for this to be safe.
@@ -933,7 +897,7 @@ static void ceph_set_dentry_offset(struct dentry *dn)
  * the caller) if we fail.
  */
 static struct dentry *splice_dentry(struct dentry *dn, struct inode *in,
-                                   bool *prehash, bool set_offset)
+                                   bool *prehash)
 {
        struct dentry *realdn;
 
@@ -965,8 +929,6 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in,
        }
        if ((!prehash || *prehash) && d_unhashed(dn))
                d_rehash(dn);
-       if (set_offset)
-               ceph_set_dentry_offset(dn);
 out:
        return dn;
 }
@@ -987,7 +949,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
 {
        struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info;
        struct inode *in = NULL;
-       struct ceph_mds_reply_inode *ininfo;
        struct ceph_vino vino;
        struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
        int err = 0;
@@ -1161,6 +1122,9 @@ retry_lookup:
 
                /* rename? */
                if (req->r_old_dentry && req->r_op == CEPH_MDS_OP_RENAME) {
+                       struct inode *olddir = req->r_old_dentry_dir;
+                       BUG_ON(!olddir);
+
                        dout(" src %p '%.*s' dst %p '%.*s'\n",
                             req->r_old_dentry,
                             req->r_old_dentry->d_name.len,
@@ -1180,13 +1144,10 @@ retry_lookup:
                           rehashing bug in vfs_rename_dir */
                        ceph_invalidate_dentry_lease(dn);
 
-                       /*
-                        * d_move() puts the renamed dentry at the end of
-                        * d_subdirs.  We need to assign it an appropriate
-                        * directory offset so we can behave when dir is
-                        * complete.
-                        */
-                       ceph_set_dentry_offset(req->r_old_dentry);
+                       /* d_move screws up sibling dentries' offsets */
+                       ceph_dir_clear_complete(dir);
+                       ceph_dir_clear_complete(olddir);
+
                        dout("dn %p gets new offset %lld\n", req->r_old_dentry,
                             ceph_dentry(req->r_old_dentry)->offset);
 
@@ -1213,8 +1174,9 @@ retry_lookup:
 
                /* attach proper inode */
                if (!dn->d_inode) {
+                       ceph_dir_clear_complete(dir);
                        ihold(in);
-                       dn = splice_dentry(dn, in, &have_lease, true);
+                       dn = splice_dentry(dn, in, &have_lease);
                        if (IS_ERR(dn)) {
                                err = PTR_ERR(dn);
                                goto done;
@@ -1235,17 +1197,16 @@ retry_lookup:
                   (req->r_op == CEPH_MDS_OP_LOOKUPSNAP ||
                    req->r_op == CEPH_MDS_OP_MKSNAP)) {
                struct dentry *dn = req->r_dentry;
+               struct inode *dir = req->r_locked_dir;
 
                /* fill out a snapdir LOOKUPSNAP dentry */
                BUG_ON(!dn);
-               BUG_ON(!req->r_locked_dir);
-               BUG_ON(ceph_snap(req->r_locked_dir) != CEPH_SNAPDIR);
-               ininfo = rinfo->targeti.in;
-               vino.ino = le64_to_cpu(ininfo->ino);
-               vino.snap = le64_to_cpu(ininfo->snapid);
+               BUG_ON(!dir);
+               BUG_ON(ceph_snap(dir) != CEPH_SNAPDIR);
                dout(" linking snapped dir %p to dn %p\n", in, dn);
+               ceph_dir_clear_complete(dir);
                ihold(in);
-               dn = splice_dentry(dn, in, NULL, true);
+               dn = splice_dentry(dn, in, NULL);
                if (IS_ERR(dn)) {
                        err = PTR_ERR(dn);
                        goto done;
@@ -1407,7 +1368,7 @@ retry_lookup:
                }
 
                if (!dn->d_inode) {
-                       dn = splice_dentry(dn, in, NULL, false);
+                       dn = splice_dentry(dn, in, NULL);
                        if (IS_ERR(dn)) {
                                err = PTR_ERR(dn);
                                dn = NULL;
index fdf941b44ff103a2590a3804aa850e468ec980d6..a822a6e58290bbedfb0e363bf3bbb601075891fb 100644 (file)
@@ -109,6 +109,8 @@ static long ceph_ioctl_set_layout(struct file *file, void __user *arg)
                return PTR_ERR(req);
        req->r_inode = inode;
        ihold(inode);
+       req->r_num_caps = 1;
+
        req->r_inode_drop = CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_EXCL;
 
        req->r_args.setlayout.layout.fl_stripe_unit =
@@ -153,6 +155,7 @@ static long ceph_ioctl_set_layout_policy (struct file *file, void __user *arg)
                return PTR_ERR(req);
        req->r_inode = inode;
        ihold(inode);
+       req->r_num_caps = 1;
 
        req->r_args.setlayout.layout.fl_stripe_unit =
                        cpu_to_le32(l.stripe_unit);
index d94ba0df9f4d195cabf677fcdcd41cc01096c7e7..191398852a2e8927b1ac193b53ceea623829caf1 100644 (file)
@@ -45,6 +45,7 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file,
                return PTR_ERR(req);
        req->r_inode = inode;
        ihold(inode);
+       req->r_num_caps = 1;
 
        /* mds requires start and length rather than start and end */
        if (LLONG_MAX == fl->fl_end)
index 7866cd05a6bbee4afd2478f3737d0ccd8ac28975..ead05cc1f447562271578131ab25769257080915 100644 (file)
@@ -266,7 +266,6 @@ struct ceph_inode_info {
        struct timespec i_rctime;
        u64 i_rbytes, i_rfiles, i_rsubdirs;
        u64 i_files, i_subdirs;
-       u64 i_max_offset;  /* largest readdir offset, set with complete dir */
 
        struct rb_root i_fragtree;
        struct mutex i_fragtree_mutex;
index aadc2b68678b7d70c0381d10c847c86624589c4c..a22d667f1069e5eb8485d121f241725de732b8a9 100644 (file)
@@ -1737,6 +1737,9 @@ cifs_inode_needs_reval(struct inode *inode)
        if (cifs_i->time == 0)
                return true;
 
+       if (!cifs_sb->actimeo)
+               return true;
+
        if (!time_in_range(jiffies, cifs_i->time,
                                cifs_i->time + cifs_sb->actimeo))
                return true;
index 40707d88a9452aea7c995198c2d94bfb1e9775c5..be2bea834bf459563e2d03e1e0fa8dec97b49c70 100644 (file)
@@ -246,16 +246,8 @@ static void __d_free(struct rcu_head *head)
        kmem_cache_free(dentry_cache, dentry); 
 }
 
-/*
- * no locks, please.
- */
-static void d_free(struct dentry *dentry)
+static void dentry_free(struct dentry *dentry)
 {
-       BUG_ON((int)dentry->d_lockref.count > 0);
-       this_cpu_dec(nr_dentry);
-       if (dentry->d_op && dentry->d_op->d_release)
-               dentry->d_op->d_release(dentry);
-
        /* if dentry was never visible to RCU, immediate free is OK */
        if (!(dentry->d_flags & DCACHE_RCUACCESS))
                __d_free(&dentry->d_u.d_rcu);
@@ -403,56 +395,6 @@ static void dentry_lru_add(struct dentry *dentry)
                d_lru_add(dentry);
 }
 
-/*
- * Remove a dentry with references from the LRU.
- *
- * If we are on the shrink list, then we can get to try_prune_one_dentry() and
- * lose our last reference through the parent walk. In this case, we need to
- * remove ourselves from the shrink list, not the LRU.
- */
-static void dentry_lru_del(struct dentry *dentry)
-{
-       if (dentry->d_flags & DCACHE_LRU_LIST) {
-               if (dentry->d_flags & DCACHE_SHRINK_LIST)
-                       return d_shrink_del(dentry);
-               d_lru_del(dentry);
-       }
-}
-
-/**
- * d_kill - kill dentry and return parent
- * @dentry: dentry to kill
- * @parent: parent dentry
- *
- * The dentry must already be unhashed and removed from the LRU.
- *
- * If this is the root of the dentry tree, return NULL.
- *
- * dentry->d_lock and parent->d_lock must be held by caller, and are dropped by
- * d_kill.
- */
-static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
-       __releases(dentry->d_lock)
-       __releases(parent->d_lock)
-       __releases(dentry->d_inode->i_lock)
-{
-       list_del(&dentry->d_u.d_child);
-       /*
-        * Inform d_walk() that we are no longer attached to the
-        * dentry tree
-        */
-       dentry->d_flags |= DCACHE_DENTRY_KILLED;
-       if (parent)
-               spin_unlock(&parent->d_lock);
-       dentry_iput(dentry);
-       /*
-        * dentry_iput drops the locks, at which point nobody (except
-        * transient RCU lookups) can reach this dentry.
-        */
-       d_free(dentry);
-       return parent;
-}
-
 /**
  * d_drop - drop a dentry
  * @dentry: dentry to drop
@@ -499,37 +441,12 @@ void d_drop(struct dentry *dentry)
 }
 EXPORT_SYMBOL(d_drop);
 
-/*
- * Finish off a dentry we've decided to kill.
- * dentry->d_lock must be held, returns with it unlocked.
- * If ref is non-zero, then decrement the refcount too.
- * Returns dentry requiring refcount drop, or NULL if we're done.
- */
-static struct dentry *
-dentry_kill(struct dentry *dentry, int unlock_on_failure)
-       __releases(dentry->d_lock)
+static void __dentry_kill(struct dentry *dentry)
 {
-       struct inode *inode;
-       struct dentry *parent;
-
-       inode = dentry->d_inode;
-       if (inode && !spin_trylock(&inode->i_lock)) {
-relock:
-               if (unlock_on_failure) {
-                       spin_unlock(&dentry->d_lock);
-                       cpu_relax();
-               }
-               return dentry; /* try again with same dentry */
-       }
-       if (IS_ROOT(dentry))
-               parent = NULL;
-       else
+       struct dentry *parent = NULL;
+       bool can_free = true;
+       if (!IS_ROOT(dentry))
                parent = dentry->d_parent;
-       if (parent && !spin_trylock(&parent->d_lock)) {
-               if (inode)
-                       spin_unlock(&inode->i_lock);
-               goto relock;
-       }
 
        /*
         * The dentry is now unrecoverably dead to the world.
@@ -543,10 +460,103 @@ relock:
        if ((dentry->d_flags & DCACHE_OP_PRUNE) && !d_unhashed(dentry))
                dentry->d_op->d_prune(dentry);
 
-       dentry_lru_del(dentry);
+       if (dentry->d_flags & DCACHE_LRU_LIST) {
+               if (!(dentry->d_flags & DCACHE_SHRINK_LIST))
+                       d_lru_del(dentry);
+       }
        /* if it was on the hash then remove it */
        __d_drop(dentry);
-       return d_kill(dentry, parent);
+       list_del(&dentry->d_u.d_child);
+       /*
+        * Inform d_walk() that we are no longer attached to the
+        * dentry tree
+        */
+       dentry->d_flags |= DCACHE_DENTRY_KILLED;
+       if (parent)
+               spin_unlock(&parent->d_lock);
+       dentry_iput(dentry);
+       /*
+        * dentry_iput drops the locks, at which point nobody (except
+        * transient RCU lookups) can reach this dentry.
+        */
+       BUG_ON((int)dentry->d_lockref.count > 0);
+       this_cpu_dec(nr_dentry);
+       if (dentry->d_op && dentry->d_op->d_release)
+               dentry->d_op->d_release(dentry);
+
+       spin_lock(&dentry->d_lock);
+       if (dentry->d_flags & DCACHE_SHRINK_LIST) {
+               dentry->d_flags |= DCACHE_MAY_FREE;
+               can_free = false;
+       }
+       spin_unlock(&dentry->d_lock);
+       if (likely(can_free))
+               dentry_free(dentry);
+}
+
+/*
+ * Finish off a dentry we've decided to kill.
+ * dentry->d_lock must be held, returns with it unlocked.
+ * If ref is non-zero, then decrement the refcount too.
+ * Returns dentry requiring refcount drop, or NULL if we're done.
+ */
+static struct dentry *dentry_kill(struct dentry *dentry)
+       __releases(dentry->d_lock)
+{
+       struct inode *inode = dentry->d_inode;
+       struct dentry *parent = NULL;
+
+       if (inode && unlikely(!spin_trylock(&inode->i_lock)))
+               goto failed;
+
+       if (!IS_ROOT(dentry)) {
+               parent = dentry->d_parent;
+               if (unlikely(!spin_trylock(&parent->d_lock))) {
+                       if (inode)
+                               spin_unlock(&inode->i_lock);
+                       goto failed;
+               }
+       }
+
+       __dentry_kill(dentry);
+       return parent;
+
+failed:
+       spin_unlock(&dentry->d_lock);
+       cpu_relax();
+       return dentry; /* try again with same dentry */
+}
+
+static inline struct dentry *lock_parent(struct dentry *dentry)
+{
+       struct dentry *parent = dentry->d_parent;
+       if (IS_ROOT(dentry))
+               return NULL;
+       if (likely(spin_trylock(&parent->d_lock)))
+               return parent;
+       spin_unlock(&dentry->d_lock);
+       rcu_read_lock();
+again:
+       parent = ACCESS_ONCE(dentry->d_parent);
+       spin_lock(&parent->d_lock);
+       /*
+        * We can't blindly lock dentry until we are sure
+        * that we won't violate the locking order.
+        * Any changes of dentry->d_parent must have
+        * been done with parent->d_lock held, so
+        * spin_lock() above is enough of a barrier
+        * for checking if it's still our child.
+        */
+       if (unlikely(parent != dentry->d_parent)) {
+               spin_unlock(&parent->d_lock);
+               goto again;
+       }
+       rcu_read_unlock();
+       if (parent != dentry)
+               spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
+       else
+               parent = NULL;
+       return parent;
 }
 
 /* 
@@ -602,7 +612,7 @@ repeat:
        return;
 
 kill_it:
-       dentry = dentry_kill(dentry, 1);
+       dentry = dentry_kill(dentry);
        if (dentry)
                goto repeat;
 }
@@ -815,64 +825,15 @@ restart:
 }
 EXPORT_SYMBOL(d_prune_aliases);
 
-/*
- * Try to throw away a dentry - free the inode, dput the parent.
- * Requires dentry->d_lock is held, and dentry->d_count == 0.
- * Releases dentry->d_lock.
- *
- * This may fail if locks cannot be acquired no problem, just try again.
- */
-static struct dentry * try_prune_one_dentry(struct dentry *dentry)
-       __releases(dentry->d_lock)
-{
-       struct dentry *parent;
-
-       parent = dentry_kill(dentry, 0);
-       /*
-        * If dentry_kill returns NULL, we have nothing more to do.
-        * if it returns the same dentry, trylocks failed. In either
-        * case, just loop again.
-        *
-        * Otherwise, we need to prune ancestors too. This is necessary
-        * to prevent quadratic behavior of shrink_dcache_parent(), but
-        * is also expected to be beneficial in reducing dentry cache
-        * fragmentation.
-        */
-       if (!parent)
-               return NULL;
-       if (parent == dentry)
-               return dentry;
-
-       /* Prune ancestors. */
-       dentry = parent;
-       while (dentry) {
-               if (lockref_put_or_lock(&dentry->d_lockref))
-                       return NULL;
-               dentry = dentry_kill(dentry, 1);
-       }
-       return NULL;
-}
-
 static void shrink_dentry_list(struct list_head *list)
 {
-       struct dentry *dentry;
-
-       rcu_read_lock();
-       for (;;) {
-               dentry = list_entry_rcu(list->prev, struct dentry, d_lru);
-               if (&dentry->d_lru == list)
-                       break; /* empty */
+       struct dentry *dentry, *parent;
 
-               /*
-                * Get the dentry lock, and re-verify that the dentry is
-                * this on the shrinking list. If it is, we know that
-                * DCACHE_SHRINK_LIST and DCACHE_LRU_LIST are set.
-                */
+       while (!list_empty(list)) {
+               struct inode *inode;
+               dentry = list_entry(list->prev, struct dentry, d_lru);
                spin_lock(&dentry->d_lock);
-               if (dentry != list_entry(list->prev, struct dentry, d_lru)) {
-                       spin_unlock(&dentry->d_lock);
-                       continue;
-               }
+               parent = lock_parent(dentry);
 
                /*
                 * The dispose list is isolated and dentries are not accounted
@@ -885,30 +846,63 @@ static void shrink_dentry_list(struct list_head *list)
                 * We found an inuse dentry which was not removed from
                 * the LRU because of laziness during lookup. Do not free it.
                 */
-               if (dentry->d_lockref.count) {
+               if ((int)dentry->d_lockref.count > 0) {
                        spin_unlock(&dentry->d_lock);
+                       if (parent)
+                               spin_unlock(&parent->d_lock);
                        continue;
                }
-               rcu_read_unlock();
 
-               /*
-                * If 'try_to_prune()' returns a dentry, it will
-                * be the same one we passed in, and d_lock will
-                * have been held the whole time, so it will not
-                * have been added to any other lists. We failed
-                * to get the inode lock.
-                *
-                * We just add it back to the shrink list.
-                */
-               dentry = try_prune_one_dentry(dentry);
 
-               rcu_read_lock();
-               if (dentry) {
+               if (unlikely(dentry->d_flags & DCACHE_DENTRY_KILLED)) {
+                       bool can_free = dentry->d_flags & DCACHE_MAY_FREE;
+                       spin_unlock(&dentry->d_lock);
+                       if (parent)
+                               spin_unlock(&parent->d_lock);
+                       if (can_free)
+                               dentry_free(dentry);
+                       continue;
+               }
+
+               inode = dentry->d_inode;
+               if (inode && unlikely(!spin_trylock(&inode->i_lock))) {
                        d_shrink_add(dentry, list);
                        spin_unlock(&dentry->d_lock);
+                       if (parent)
+                               spin_unlock(&parent->d_lock);
+                       continue;
+               }
+
+               __dentry_kill(dentry);
+
+               /*
+                * We need to prune ancestors too. This is necessary to prevent
+                * quadratic behavior of shrink_dcache_parent(), but is also
+                * expected to be beneficial in reducing dentry cache
+                * fragmentation.
+                */
+               dentry = parent;
+               while (dentry && !lockref_put_or_lock(&dentry->d_lockref)) {
+                       parent = lock_parent(dentry);
+                       if (dentry->d_lockref.count != 1) {
+                               dentry->d_lockref.count--;
+                               spin_unlock(&dentry->d_lock);
+                               if (parent)
+                                       spin_unlock(&parent->d_lock);
+                               break;
+                       }
+                       inode = dentry->d_inode;        /* can't be NULL */
+                       if (unlikely(!spin_trylock(&inode->i_lock))) {
+                               spin_unlock(&dentry->d_lock);
+                               if (parent)
+                                       spin_unlock(&parent->d_lock);
+                               cpu_relax();
+                               continue;
+                       }
+                       __dentry_kill(dentry);
+                       dentry = parent;
                }
        }
-       rcu_read_unlock();
 }
 
 static enum lru_status
@@ -1261,34 +1255,23 @@ static enum d_walk_ret select_collect(void *_data, struct dentry *dentry)
        if (data->start == dentry)
                goto out;
 
-       /*
-        * move only zero ref count dentries to the dispose list.
-        *
-        * Those which are presently on the shrink list, being processed
-        * by shrink_dentry_list(), shouldn't be moved.  Otherwise the
-        * loop in shrink_dcache_parent() might not make any progress
-        * and loop forever.
-        */
-       if (dentry->d_lockref.count) {
-               dentry_lru_del(dentry);
-       } else if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) {
-               /*
-                * We can't use d_lru_shrink_move() because we
-                * need to get the global LRU lock and do the
-                * LRU accounting.
-                */
-               d_lru_del(dentry);
-               d_shrink_add(dentry, &data->dispose);
+       if (dentry->d_flags & DCACHE_SHRINK_LIST) {
                data->found++;
-               ret = D_WALK_NORETRY;
+       } else {
+               if (dentry->d_flags & DCACHE_LRU_LIST)
+                       d_lru_del(dentry);
+               if (!dentry->d_lockref.count) {
+                       d_shrink_add(dentry, &data->dispose);
+                       data->found++;
+               }
        }
        /*
         * We can return to the caller if we have found some (this
         * ensures forward progress). We'll be coming back to find
         * the rest.
         */
-       if (data->found && need_resched())
-               ret = D_WALK_QUIT;
+       if (!list_empty(&data->dispose))
+               ret = need_resched() ? D_WALK_QUIT : D_WALK_NORETRY;
 out:
        return ret;
 }
@@ -1318,45 +1301,35 @@ void shrink_dcache_parent(struct dentry *parent)
 }
 EXPORT_SYMBOL(shrink_dcache_parent);
 
-static enum d_walk_ret umount_collect(void *_data, struct dentry *dentry)
+static enum d_walk_ret umount_check(void *_data, struct dentry *dentry)
 {
-       struct select_data *data = _data;
-       enum d_walk_ret ret = D_WALK_CONTINUE;
+       /* it has busy descendents; complain about those instead */
+       if (!list_empty(&dentry->d_subdirs))
+               return D_WALK_CONTINUE;
 
-       if (dentry->d_lockref.count) {
-               dentry_lru_del(dentry);
-               if (likely(!list_empty(&dentry->d_subdirs)))
-                       goto out;
-               if (dentry == data->start && dentry->d_lockref.count == 1)
-                       goto out;
-               printk(KERN_ERR
-                      "BUG: Dentry %p{i=%lx,n=%s}"
-                      " still in use (%d)"
-                      " [unmount of %s %s]\n",
+       /* root with refcount 1 is fine */
+       if (dentry == _data && dentry->d_lockref.count == 1)
+               return D_WALK_CONTINUE;
+
+       printk(KERN_ERR "BUG: Dentry %p{i=%lx,n=%pd} "
+                       " still in use (%d) [unmount of %s %s]\n",
                       dentry,
                       dentry->d_inode ?
                       dentry->d_inode->i_ino : 0UL,
-                      dentry->d_name.name,
+                      dentry,
                       dentry->d_lockref.count,
                       dentry->d_sb->s_type->name,
                       dentry->d_sb->s_id);
-               BUG();
-       } else if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) {
-               /*
-                * We can't use d_lru_shrink_move() because we
-                * need to get the global LRU lock and do the
-                * LRU accounting.
-                */
-               if (dentry->d_flags & DCACHE_LRU_LIST)
-                       d_lru_del(dentry);
-               d_shrink_add(dentry, &data->dispose);
-               data->found++;
-               ret = D_WALK_NORETRY;
-       }
-out:
-       if (data->found && need_resched())
-               ret = D_WALK_QUIT;
-       return ret;
+       WARN_ON(1);
+       return D_WALK_CONTINUE;
+}
+
+static void do_one_tree(struct dentry *dentry)
+{
+       shrink_dcache_parent(dentry);
+       d_walk(dentry, dentry, umount_check, NULL);
+       d_drop(dentry);
+       dput(dentry);
 }
 
 /*
@@ -1366,40 +1339,15 @@ void shrink_dcache_for_umount(struct super_block *sb)
 {
        struct dentry *dentry;
 
-       if (down_read_trylock(&sb->s_umount))
-               BUG();
+       WARN(down_read_trylock(&sb->s_umount), "s_umount should've been locked");
 
        dentry = sb->s_root;
        sb->s_root = NULL;
-       for (;;) {
-               struct select_data data;
-
-               INIT_LIST_HEAD(&data.dispose);
-               data.start = dentry;
-               data.found = 0;
-
-               d_walk(dentry, &data, umount_collect, NULL);
-               if (!data.found)
-                       break;
-
-               shrink_dentry_list(&data.dispose);
-               cond_resched();
-       }
-       d_drop(dentry);
-       dput(dentry);
+       do_one_tree(dentry);
 
        while (!hlist_bl_empty(&sb->s_anon)) {
-               struct select_data data;
-               dentry = hlist_bl_entry(hlist_bl_first(&sb->s_anon), struct dentry, d_hash);
-
-               INIT_LIST_HEAD(&data.dispose);
-               data.start = NULL;
-               data.found = 0;
-
-               d_walk(dentry, &data, umount_collect, NULL);
-               if (data.found)
-                       shrink_dentry_list(&data.dispose);
-               cond_resched();
+               dentry = dget(hlist_bl_entry(hlist_bl_first(&sb->s_anon), struct dentry, d_hash));
+               do_one_tree(dentry);
        }
 }
 
@@ -1647,8 +1595,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
        unsigned add_flags = d_flags_for_inode(inode);
 
        spin_lock(&dentry->d_lock);
-       dentry->d_flags &= ~DCACHE_ENTRY_TYPE;
-       dentry->d_flags |= add_flags;
+       __d_set_type(dentry, add_flags);
        if (inode)
                hlist_add_head(&dentry->d_alias, &inode->i_dentry);
        dentry->d_inode = inode;
index 476f3ebf437ef40ddd7432200080825b7e9e992c..238b7aa26f68ab538df0cc219073a3d26541cc11 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -657,10 +657,10 @@ int setup_arg_pages(struct linux_binprm *bprm,
        unsigned long rlim_stack;
 
 #ifdef CONFIG_STACK_GROWSUP
-       /* Limit stack size to 1GB */
+       /* Limit stack size */
        stack_base = rlimit_max(RLIMIT_STACK);
-       if (stack_base > (1 << 30))
-               stack_base = 1 << 30;
+       if (stack_base > STACK_SIZE_MAX)
+               stack_base = STACK_SIZE_MAX;
 
        /* Make sure we didn't let the argument array grow too large. */
        if (vma->vm_end - vma->vm_start > stack_base)
index a0b0855d00a985c78288074f9adc813d14addfe1..205e0d5d530752532bcb045b4630ddee0ded7ffd 100644 (file)
@@ -348,7 +348,7 @@ int __init fuse_ctl_init(void)
        return register_filesystem(&fuse_ctl_fs_type);
 }
 
-void fuse_ctl_cleanup(void)
+void __exit fuse_ctl_cleanup(void)
 {
        unregister_filesystem(&fuse_ctl_fs_type);
 }
index 5b4e035b364cc604d68e72411337ef061a766fea..42198359fa1b472557e44f325e9f55c305237e99 100644 (file)
@@ -679,6 +679,14 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
        return create_new_entry(fc, req, dir, entry, S_IFLNK);
 }
 
+static inline void fuse_update_ctime(struct inode *inode)
+{
+       if (!IS_NOCMTIME(inode)) {
+               inode->i_ctime = current_fs_time(inode->i_sb);
+               mark_inode_dirty_sync(inode);
+       }
+}
+
 static int fuse_unlink(struct inode *dir, struct dentry *entry)
 {
        int err;
@@ -713,6 +721,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
                fuse_invalidate_attr(inode);
                fuse_invalidate_attr(dir);
                fuse_invalidate_entry_cache(entry);
+               fuse_update_ctime(inode);
        } else if (err == -EINTR)
                fuse_invalidate_entry(entry);
        return err;
@@ -743,23 +752,26 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
        return err;
 }
 
-static int fuse_rename(struct inode *olddir, struct dentry *oldent,
-                      struct inode *newdir, struct dentry *newent)
+static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
+                             struct inode *newdir, struct dentry *newent,
+                             unsigned int flags, int opcode, size_t argsize)
 {
        int err;
-       struct fuse_rename_in inarg;
+       struct fuse_rename2_in inarg;
        struct fuse_conn *fc = get_fuse_conn(olddir);
-       struct fuse_req *req = fuse_get_req_nopages(fc);
+       struct fuse_req *req;
 
+       req = fuse_get_req_nopages(fc);
        if (IS_ERR(req))
                return PTR_ERR(req);
 
-       memset(&inarg, 0, sizeof(inarg));
+       memset(&inarg, 0, argsize);
        inarg.newdir = get_node_id(newdir);
-       req->in.h.opcode = FUSE_RENAME;
+       inarg.flags = flags;
+       req->in.h.opcode = opcode;
        req->in.h.nodeid = get_node_id(olddir);
        req->in.numargs = 3;
-       req->in.args[0].size = sizeof(inarg);
+       req->in.args[0].size = argsize;
        req->in.args[0].value = &inarg;
        req->in.args[1].size = oldent->d_name.len + 1;
        req->in.args[1].value = oldent->d_name.name;
@@ -771,15 +783,22 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent,
        if (!err) {
                /* ctime changes */
                fuse_invalidate_attr(oldent->d_inode);
+               fuse_update_ctime(oldent->d_inode);
+
+               if (flags & RENAME_EXCHANGE) {
+                       fuse_invalidate_attr(newent->d_inode);
+                       fuse_update_ctime(newent->d_inode);
+               }
 
                fuse_invalidate_attr(olddir);
                if (olddir != newdir)
                        fuse_invalidate_attr(newdir);
 
                /* newent will end up negative */
-               if (newent->d_inode) {
+               if (!(flags & RENAME_EXCHANGE) && newent->d_inode) {
                        fuse_invalidate_attr(newent->d_inode);
                        fuse_invalidate_entry_cache(newent);
+                       fuse_update_ctime(newent->d_inode);
                }
        } else if (err == -EINTR) {
                /* If request was interrupted, DEITY only knows if the
@@ -795,6 +814,36 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent,
        return err;
 }
 
+static int fuse_rename(struct inode *olddir, struct dentry *oldent,
+                      struct inode *newdir, struct dentry *newent)
+{
+       return fuse_rename_common(olddir, oldent, newdir, newent, 0,
+                                 FUSE_RENAME, sizeof(struct fuse_rename_in));
+}
+
+static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
+                       struct inode *newdir, struct dentry *newent,
+                       unsigned int flags)
+{
+       struct fuse_conn *fc = get_fuse_conn(olddir);
+       int err;
+
+       if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
+               return -EINVAL;
+
+       if (fc->no_rename2 || fc->minor < 23)
+               return -EINVAL;
+
+       err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
+                                FUSE_RENAME2, sizeof(struct fuse_rename2_in));
+       if (err == -ENOSYS) {
+               fc->no_rename2 = 1;
+               err = -EINVAL;
+       }
+       return err;
+
+}
+
 static int fuse_link(struct dentry *entry, struct inode *newdir,
                     struct dentry *newent)
 {
@@ -829,6 +878,7 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
                inc_nlink(inode);
                spin_unlock(&fc->lock);
                fuse_invalidate_attr(inode);
+               fuse_update_ctime(inode);
        } else if (err == -EINTR) {
                fuse_invalidate_attr(inode);
        }
@@ -846,6 +896,8 @@ static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
                attr->size = i_size_read(inode);
                attr->mtime = inode->i_mtime.tv_sec;
                attr->mtimensec = inode->i_mtime.tv_nsec;
+               attr->ctime = inode->i_ctime.tv_sec;
+               attr->ctimensec = inode->i_ctime.tv_nsec;
        }
 
        stat->dev = inode->i_sb->s_dev;
@@ -1504,7 +1556,7 @@ static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
 }
 
 static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
-                          bool trust_local_mtime)
+                          bool trust_local_cmtime)
 {
        unsigned ivalid = iattr->ia_valid;
 
@@ -1523,13 +1575,18 @@ static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
                if (!(ivalid & ATTR_ATIME_SET))
                        arg->valid |= FATTR_ATIME_NOW;
        }
-       if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_mtime)) {
+       if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
                arg->valid |= FATTR_MTIME;
                arg->mtime = iattr->ia_mtime.tv_sec;
                arg->mtimensec = iattr->ia_mtime.tv_nsec;
-               if (!(ivalid & ATTR_MTIME_SET) && !trust_local_mtime)
+               if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
                        arg->valid |= FATTR_MTIME_NOW;
        }
+       if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
+               arg->valid |= FATTR_CTIME;
+               arg->ctime = iattr->ia_ctime.tv_sec;
+               arg->ctimensec = iattr->ia_ctime.tv_nsec;
+       }
 }
 
 /*
@@ -1597,39 +1654,38 @@ static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_req *req,
 /*
  * Flush inode->i_mtime to the server
  */
-int fuse_flush_mtime(struct file *file, bool nofail)
+int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
 {
-       struct inode *inode = file->f_mapping->host;
-       struct fuse_inode *fi = get_fuse_inode(inode);
        struct fuse_conn *fc = get_fuse_conn(inode);
-       struct fuse_req *req = NULL;
+       struct fuse_req *req;
        struct fuse_setattr_in inarg;
        struct fuse_attr_out outarg;
        int err;
 
-       if (nofail) {
-               req = fuse_get_req_nofail_nopages(fc, file);
-       } else {
-               req = fuse_get_req_nopages(fc);
-               if (IS_ERR(req))
-                       return PTR_ERR(req);
-       }
+       req = fuse_get_req_nopages(fc);
+       if (IS_ERR(req))
+               return PTR_ERR(req);
 
        memset(&inarg, 0, sizeof(inarg));
        memset(&outarg, 0, sizeof(outarg));
 
-       inarg.valid |= FATTR_MTIME;
+       inarg.valid = FATTR_MTIME;
        inarg.mtime = inode->i_mtime.tv_sec;
        inarg.mtimensec = inode->i_mtime.tv_nsec;
-
+       if (fc->minor >= 23) {
+               inarg.valid |= FATTR_CTIME;
+               inarg.ctime = inode->i_ctime.tv_sec;
+               inarg.ctimensec = inode->i_ctime.tv_nsec;
+       }
+       if (ff) {
+               inarg.valid |= FATTR_FH;
+               inarg.fh = ff->fh;
+       }
        fuse_setattr_fill(fc, req, inode, &inarg, &outarg);
        fuse_request_send(fc, req);
        err = req->out.h.error;
        fuse_put_request(fc, req);
 
-       if (!err)
-               clear_bit(FUSE_I_MTIME_DIRTY, &fi->state);
-
        return err;
 }
 
@@ -1653,7 +1709,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
        bool is_wb = fc->writeback_cache;
        loff_t oldsize;
        int err;
-       bool trust_local_mtime = is_wb && S_ISREG(inode->i_mode);
+       bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode);
 
        if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
                attr->ia_valid |= ATTR_FORCE;
@@ -1678,11 +1734,13 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
        if (is_truncate) {
                fuse_set_nowrite(inode);
                set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
+               if (trust_local_cmtime && attr->ia_size != inode->i_size)
+                       attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
        }
 
        memset(&inarg, 0, sizeof(inarg));
        memset(&outarg, 0, sizeof(outarg));
-       iattr_to_fattr(attr, &inarg, trust_local_mtime);
+       iattr_to_fattr(attr, &inarg, trust_local_cmtime);
        if (file) {
                struct fuse_file *ff = file->private_data;
                inarg.valid |= FATTR_FH;
@@ -1711,9 +1769,12 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
 
        spin_lock(&fc->lock);
        /* the kernel maintains i_mtime locally */
-       if (trust_local_mtime && (attr->ia_valid & ATTR_MTIME)) {
-               inode->i_mtime = attr->ia_mtime;
-               clear_bit(FUSE_I_MTIME_DIRTY, &fi->state);
+       if (trust_local_cmtime) {
+               if (attr->ia_valid & ATTR_MTIME)
+                       inode->i_mtime = attr->ia_mtime;
+               if (attr->ia_valid & ATTR_CTIME)
+                       inode->i_ctime = attr->ia_ctime;
+               /* FIXME: clear I_DIRTY_SYNC? */
        }
 
        fuse_change_attributes_common(inode, &outarg.attr,
@@ -1810,8 +1871,10 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
                fc->no_setxattr = 1;
                err = -EOPNOTSUPP;
        }
-       if (!err)
+       if (!err) {
                fuse_invalidate_attr(inode);
+               fuse_update_ctime(inode);
+       }
        return err;
 }
 
@@ -1941,20 +2004,11 @@ static int fuse_removexattr(struct dentry *entry, const char *name)
                fc->no_removexattr = 1;
                err = -EOPNOTSUPP;
        }
-       if (!err)
+       if (!err) {
                fuse_invalidate_attr(inode);
-       return err;
-}
-
-static int fuse_update_time(struct inode *inode, struct timespec *now,
-                           int flags)
-{
-       if (flags & S_MTIME) {
-               inode->i_mtime = *now;
-               set_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state);
-               BUG_ON(!S_ISREG(inode->i_mode));
+               fuse_update_ctime(inode);
        }
-       return 0;
+       return err;
 }
 
 static const struct inode_operations fuse_dir_inode_operations = {
@@ -1964,6 +2018,7 @@ static const struct inode_operations fuse_dir_inode_operations = {
        .unlink         = fuse_unlink,
        .rmdir          = fuse_rmdir,
        .rename         = fuse_rename,
+       .rename2        = fuse_rename2,
        .link           = fuse_link,
        .setattr        = fuse_setattr,
        .create         = fuse_create,
@@ -1996,7 +2051,6 @@ static const struct inode_operations fuse_common_inode_operations = {
        .getxattr       = fuse_getxattr,
        .listxattr      = fuse_listxattr,
        .removexattr    = fuse_removexattr,
-       .update_time    = fuse_update_time,
 };
 
 static const struct inode_operations fuse_symlink_inode_operations = {
index 13f8bdec5110d1a7db12b2a262bb5e2ecb0e4f82..96d513e01a5d534e8717622a4fb2c7b20bb98d64 100644 (file)
@@ -223,6 +223,8 @@ void fuse_finish_open(struct inode *inode, struct file *file)
                i_size_write(inode, 0);
                spin_unlock(&fc->lock);
                fuse_invalidate_attr(inode);
+               if (fc->writeback_cache)
+                       file_update_time(file);
        }
        if ((file->f_mode & FMODE_WRITE) && fc->writeback_cache)
                fuse_link_write_file(file);
@@ -232,18 +234,26 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
        int err;
+       bool lock_inode = (file->f_flags & O_TRUNC) &&
+                         fc->atomic_o_trunc &&
+                         fc->writeback_cache;
 
        err = generic_file_open(inode, file);
        if (err)
                return err;
 
+       if (lock_inode)
+               mutex_lock(&inode->i_mutex);
+
        err = fuse_do_open(fc, get_node_id(inode), file, isdir);
-       if (err)
-               return err;
 
-       fuse_finish_open(inode, file);
+       if (!err)
+               fuse_finish_open(inode, file);
 
-       return 0;
+       if (lock_inode)
+               mutex_unlock(&inode->i_mutex);
+
+       return err;
 }
 
 static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode)
@@ -314,10 +324,7 @@ static int fuse_release(struct inode *inode, struct file *file)
 
        /* see fuse_vma_close() for !writeback_cache case */
        if (fc->writeback_cache)
-               filemap_write_and_wait(file->f_mapping);
-
-       if (test_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state))
-               fuse_flush_mtime(file, true);
+               write_inode_now(inode, 1);
 
        fuse_release_common(file, FUSE_RELEASE);
 
@@ -439,7 +446,7 @@ static int fuse_flush(struct file *file, fl_owner_t id)
        if (fc->no_flush)
                return 0;
 
-       err = filemap_write_and_wait(file->f_mapping);
+       err = write_inode_now(inode, 1);
        if (err)
                return err;
 
@@ -480,13 +487,6 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
        if (is_bad_inode(inode))
                return -EIO;
 
-       err = filemap_write_and_wait_range(inode->i_mapping, start, end);
-       if (err)
-               return err;
-
-       if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
-               return 0;
-
        mutex_lock(&inode->i_mutex);
 
        /*
@@ -494,17 +494,17 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
         * wait for all outstanding writes, before sending the FSYNC
         * request.
         */
-       err = write_inode_now(inode, 0);
+       err = filemap_write_and_wait_range(inode->i_mapping, start, end);
        if (err)
                goto out;
 
        fuse_sync_writes(inode);
+       err = sync_inode_metadata(inode, 1);
+       if (err)
+               goto out;
 
-       if (test_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state)) {
-               int err = fuse_flush_mtime(file, false);
-               if (err)
-                       goto out;
-       }
+       if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
+               goto out;
 
        req = fuse_get_req_nopages(fc);
        if (IS_ERR(req)) {
@@ -1659,13 +1659,13 @@ static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_req *req)
        fuse_writepage_free(fc, req);
 }
 
-static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc,
-                                            struct fuse_inode *fi)
+static struct fuse_file *__fuse_write_file_get(struct fuse_conn *fc,
+                                              struct fuse_inode *fi)
 {
        struct fuse_file *ff = NULL;
 
        spin_lock(&fc->lock);
-       if (!WARN_ON(list_empty(&fi->write_files))) {
+       if (!list_empty(&fi->write_files)) {
                ff = list_entry(fi->write_files.next, struct fuse_file,
                                write_entry);
                fuse_file_get(ff);
@@ -1675,6 +1675,29 @@ static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc,
        return ff;
 }
 
+static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc,
+                                            struct fuse_inode *fi)
+{
+       struct fuse_file *ff = __fuse_write_file_get(fc, fi);
+       WARN_ON(!ff);
+       return ff;
+}
+
+int fuse_write_inode(struct inode *inode, struct writeback_control *wbc)
+{
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
+       struct fuse_file *ff;
+       int err;
+
+       ff = __fuse_write_file_get(fc, fi);
+       err = fuse_flush_times(inode, ff);
+       if (ff)
+               fuse_file_put(ff, 0);
+
+       return err;
+}
+
 static int fuse_writepage_locked(struct page *page)
 {
        struct address_space *mapping = page->mapping;
@@ -2972,6 +2995,9 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
        bool lock_inode = !(mode & FALLOC_FL_KEEP_SIZE) ||
                           (mode & FALLOC_FL_PUNCH_HOLE);
 
+       if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
+               return -EOPNOTSUPP;
+
        if (fc->no_fallocate)
                return -EOPNOTSUPP;
 
@@ -3017,12 +3043,8 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
        if (!(mode & FALLOC_FL_KEEP_SIZE)) {
                bool changed = fuse_write_update_size(inode, offset + length);
 
-               if (changed && fc->writeback_cache) {
-                       struct fuse_inode *fi = get_fuse_inode(inode);
-
-                       inode->i_mtime = current_fs_time(inode->i_sb);
-                       set_bit(FUSE_I_MTIME_DIRTY, &fi->state);
-               }
+               if (changed && fc->writeback_cache)
+                       file_update_time(file);
        }
 
        if (mode & FALLOC_FL_PUNCH_HOLE)
index a257ed8ebee6c6db62339e1a8d3f2f87479310ea..7aa5c75e0de13dcc9728ba890983e842c1a98554 100644 (file)
@@ -119,8 +119,6 @@ enum {
        FUSE_I_INIT_RDPLUS,
        /** An operation changing file size is in progress  */
        FUSE_I_SIZE_UNSTABLE,
-       /** i_mtime has been updated locally; a flush to userspace needed */
-       FUSE_I_MTIME_DIRTY,
 };
 
 struct fuse_conn;
@@ -544,6 +542,9 @@ struct fuse_conn {
        /** Is fallocate not implemented by fs? */
        unsigned no_fallocate:1;
 
+       /** Is rename with flags implemented by fs? */
+       unsigned no_rename2:1;
+
        /** Use enhanced/automatic page cache invalidation. */
        unsigned auto_inval_data:1;
 
@@ -725,7 +726,7 @@ int fuse_dev_init(void);
 void fuse_dev_cleanup(void);
 
 int fuse_ctl_init(void);
-void fuse_ctl_cleanup(void);
+void __exit fuse_ctl_cleanup(void);
 
 /**
  * Allocate a request
@@ -891,7 +892,8 @@ int fuse_dev_release(struct inode *inode, struct file *file);
 
 bool fuse_write_update_size(struct inode *inode, loff_t pos);
 
-int fuse_flush_mtime(struct file *file, bool nofail);
+int fuse_flush_times(struct inode *inode, struct fuse_file *ff);
+int fuse_write_inode(struct inode *inode, struct writeback_control *wbc);
 
 int fuse_do_setattr(struct inode *inode, struct iattr *attr,
                    struct file *file);
index 8d611696fcad303dfe4137a2ff9bc9e1d2a5b97d..754dcf23de8abf10ceee81926f022731b810cb54 100644 (file)
@@ -175,9 +175,9 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
        if (!fc->writeback_cache || !S_ISREG(inode->i_mode)) {
                inode->i_mtime.tv_sec   = attr->mtime;
                inode->i_mtime.tv_nsec  = attr->mtimensec;
+               inode->i_ctime.tv_sec   = attr->ctime;
+               inode->i_ctime.tv_nsec  = attr->ctimensec;
        }
-       inode->i_ctime.tv_sec   = attr->ctime;
-       inode->i_ctime.tv_nsec  = attr->ctimensec;
 
        if (attr->blksize != 0)
                inode->i_blkbits = ilog2(attr->blksize);
@@ -256,6 +256,8 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
        inode->i_size = attr->size;
        inode->i_mtime.tv_sec  = attr->mtime;
        inode->i_mtime.tv_nsec = attr->mtimensec;
+       inode->i_ctime.tv_sec  = attr->ctime;
+       inode->i_ctime.tv_nsec = attr->ctimensec;
        if (S_ISREG(inode->i_mode)) {
                fuse_init_common(inode);
                fuse_init_file_inode(inode);
@@ -303,7 +305,7 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
 
        if ((inode->i_state & I_NEW)) {
                inode->i_flags |= S_NOATIME;
-               if (!fc->writeback_cache || !S_ISREG(inode->i_mode))
+               if (!fc->writeback_cache || !S_ISREG(attr->mode))
                        inode->i_flags |= S_NOCMTIME;
                inode->i_generation = generation;
                inode->i_data.backing_dev_info = &fc->bdi;
@@ -788,6 +790,7 @@ static const struct super_operations fuse_super_operations = {
        .alloc_inode    = fuse_alloc_inode,
        .destroy_inode  = fuse_destroy_inode,
        .evict_inode    = fuse_evict_inode,
+       .write_inode    = fuse_write_inode,
        .drop_inode     = generic_delete_inode,
        .remount_fs     = fuse_remount_fs,
        .put_super      = fuse_put_super,
@@ -890,6 +893,11 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
                                fc->async_dio = 1;
                        if (arg->flags & FUSE_WRITEBACK_CACHE)
                                fc->writeback_cache = 1;
+                       if (arg->time_gran && arg->time_gran <= 1000000000)
+                               fc->sb->s_time_gran = arg->time_gran;
+                       else
+                               fc->sb->s_time_gran = 1000000000;
+
                } else {
                        ra_pages = fc->max_read / PAGE_CACHE_SIZE;
                        fc->no_lock = 1;
@@ -996,7 +1004,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        if (sb->s_flags & MS_MANDLOCK)
                goto err;
 
-       sb->s_flags &= ~MS_NOSEC;
+       sb->s_flags &= ~(MS_NOSEC | MS_I_VERSION);
 
        if (!parse_fuse_opt((char *) data, &d, is_bdev))
                goto err;
index 2040275209371d53d751a2cbbf92b251933c6dc6..e19d4c0cacae176bcb003e608c6872079908d92d 100644 (file)
@@ -1030,6 +1030,11 @@ static int __init init_hugetlbfs_fs(void)
        int error;
        int i;
 
+       if (!hugepages_supported()) {
+               pr_info("hugetlbfs: disabling because there are no supported hugepage sizes\n");
+               return -ENOTSUPP;
+       }
+
        error = bdi_init(&hugetlbfs_backing_dev_info);
        if (error)
                return error;
index e01ea4a14a014b3123dddf6d2ad1ecb9a6381736..5e9a80cfc3d8857c7cfe496eae627c921c47c6f2 100644 (file)
@@ -610,6 +610,7 @@ static void kernfs_put_open_node(struct kernfs_node *kn,
 static int kernfs_fop_open(struct inode *inode, struct file *file)
 {
        struct kernfs_node *kn = file->f_path.dentry->d_fsdata;
+       struct kernfs_root *root = kernfs_root(kn);
        const struct kernfs_ops *ops;
        struct kernfs_open_file *of;
        bool has_read, has_write, has_mmap;
@@ -624,14 +625,16 @@ static int kernfs_fop_open(struct inode *inode, struct file *file)
        has_write = ops->write || ops->mmap;
        has_mmap = ops->mmap;
 
-       /* check perms and supported operations */
-       if ((file->f_mode & FMODE_WRITE) &&
-           (!(inode->i_mode & S_IWUGO) || !has_write))
-               goto err_out;
+       /* see the flag definition for details */
+       if (root->flags & KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK) {
+               if ((file->f_mode & FMODE_WRITE) &&
+                   (!(inode->i_mode & S_IWUGO) || !has_write))
+                       goto err_out;
 
-       if ((file->f_mode & FMODE_READ) &&
-           (!(inode->i_mode & S_IRUGO) || !has_read))
-               goto err_out;
+               if ((file->f_mode & FMODE_READ) &&
+                   (!(inode->i_mode & S_IRUGO) || !has_read))
+                       goto err_out;
+       }
 
        /* allocate a kernfs_open_file for the file */
        error = -ENOMEM;
index e663aeac579e5d8aaa2596a177114b17f262bd6c..e390bd9ae068696d4a5425057559d3037e6f4518 100644 (file)
@@ -389,18 +389,6 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
        fl->fl_ops = NULL;
        fl->fl_lmops = NULL;
 
-       /* Ensure that fl->fl_filp has compatible f_mode */
-       switch (l->l_type) {
-       case F_RDLCK:
-               if (!(filp->f_mode & FMODE_READ))
-                       return -EBADF;
-               break;
-       case F_WRLCK:
-               if (!(filp->f_mode & FMODE_WRITE))
-                       return -EBADF;
-               break;
-       }
-
        return assign_type(fl, l->l_type);
 }
 
@@ -2034,6 +2022,22 @@ static int do_lock_file_wait(struct file *filp, unsigned int cmd,
        return error;
 }
 
+/* Ensure that fl->fl_filp has compatible f_mode for F_SETLK calls */
+static int
+check_fmode_for_setlk(struct file_lock *fl)
+{
+       switch (fl->fl_type) {
+       case F_RDLCK:
+               if (!(fl->fl_file->f_mode & FMODE_READ))
+                       return -EBADF;
+               break;
+       case F_WRLCK:
+               if (!(fl->fl_file->f_mode & FMODE_WRITE))
+                       return -EBADF;
+       }
+       return 0;
+}
+
 /* Apply the lock described by l to an open file descriptor.
  * This implements both the F_SETLK and F_SETLKW commands of fcntl().
  */
@@ -2071,6 +2075,10 @@ again:
        if (error)
                goto out;
 
+       error = check_fmode_for_setlk(file_lock);
+       if (error)
+               goto out;
+
        /*
         * If the cmd is requesting file-private locks, then set the
         * FL_OFDLCK flag and override the owner.
@@ -2206,6 +2214,10 @@ again:
        if (error)
                goto out;
 
+       error = check_fmode_for_setlk(file_lock);
+       if (error)
+               goto out;
+
        /*
         * If the cmd is requesting file-private locks, then set the
         * FL_OFDLCK flag and override the owner.
index c6157c894fce234c333d5a2d787f81ee3e5e7ba9..80168273396bbaeb4490677854fe34d637a78551 100644 (file)
@@ -1542,7 +1542,7 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
                inode = path->dentry->d_inode;
        }
        err = -ENOENT;
-       if (!inode)
+       if (!inode || d_is_negative(path->dentry))
                goto out_path_put;
 
        if (should_follow_link(path->dentry, follow)) {
@@ -2249,7 +2249,7 @@ mountpoint_last(struct nameidata *nd, struct path *path)
        mutex_unlock(&dir->d_inode->i_mutex);
 
 done:
-       if (!dentry->d_inode) {
+       if (!dentry->d_inode || d_is_negative(dentry)) {
                error = -ENOENT;
                dput(dentry);
                goto out;
@@ -2994,7 +2994,7 @@ retry_lookup:
 finish_lookup:
        /* we _can_ be in RCU mode here */
        error = -ENOENT;
-       if (d_is_negative(path->dentry)) {
+       if (!inode || d_is_negative(path->dentry)) {
                path_to_nameidata(path, nd);
                goto out;
        }
index 6f3f392d48af76d9b7bdb752f1d13eff9580be1b..f66c66b9f18285a4084114679d0e1d3e555a253c 100644 (file)
@@ -402,8 +402,10 @@ sort_pacl(struct posix_acl *pacl)
         * by uid/gid. */
        int i, j;
 
-       if (pacl->a_count <= 4)
-               return; /* no users or groups */
+       /* no users or groups */
+       if (!pacl || pacl->a_count <= 4)
+               return;
+
        i = 1;
        while (pacl->a_entries[i].e_tag == ACL_USER)
                i++;
@@ -530,13 +532,12 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
 
        /*
         * ACLs with no ACEs are treated differently in the inheritable
-        * and effective cases: when there are no inheritable ACEs, we
-        * set a zero-length default posix acl:
+        * and effective cases: when there are no inheritable ACEs,
+        * calls ->set_acl with a NULL ACL structure.
         */
-       if (state->empty && (flags & NFS4_ACL_TYPE_DEFAULT)) {
-               pacl = posix_acl_alloc(0, GFP_KERNEL);
-               return pacl ? pacl : ERR_PTR(-ENOMEM);
-       }
+       if (state->empty && (flags & NFS4_ACL_TYPE_DEFAULT))
+               return NULL;
+
        /*
         * When there are no effective ACEs, the following will end
         * up setting a 3-element effective posix ACL with all
@@ -589,7 +590,7 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
                add_to_mask(state, &state->groups->aces[i].perms);
        }
 
-       if (!state->users->n && !state->groups->n) {
+       if (state->users->n || state->groups->n) {
                pace++;
                pace->e_tag = ACL_MASK;
                low_mode_from_nfs4(state->mask.allow, &pace->e_perm, flags);
index 3ba65979a3cde006e73ed2c310e2bc42f6988fb2..9a77a5a21557c4e16740196c16d7f4f218ce2643 100644 (file)
@@ -1078,6 +1078,18 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
                return NULL;
        }
        clp->cl_name.len = name.len;
+       INIT_LIST_HEAD(&clp->cl_sessions);
+       idr_init(&clp->cl_stateids);
+       atomic_set(&clp->cl_refcount, 0);
+       clp->cl_cb_state = NFSD4_CB_UNKNOWN;
+       INIT_LIST_HEAD(&clp->cl_idhash);
+       INIT_LIST_HEAD(&clp->cl_openowners);
+       INIT_LIST_HEAD(&clp->cl_delegations);
+       INIT_LIST_HEAD(&clp->cl_lru);
+       INIT_LIST_HEAD(&clp->cl_callbacks);
+       INIT_LIST_HEAD(&clp->cl_revoked);
+       spin_lock_init(&clp->cl_lock);
+       rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table");
        return clp;
 }
 
@@ -1095,6 +1107,7 @@ free_client(struct nfs4_client *clp)
                WARN_ON_ONCE(atomic_read(&ses->se_ref));
                free_session(ses);
        }
+       rpc_destroy_wait_queue(&clp->cl_cb_waitq);
        free_svc_cred(&clp->cl_cred);
        kfree(clp->cl_name.data);
        idr_destroy(&clp->cl_stateids);
@@ -1347,7 +1360,6 @@ static struct nfs4_client *create_client(struct xdr_netobj name,
        if (clp == NULL)
                return NULL;
 
-       INIT_LIST_HEAD(&clp->cl_sessions);
        ret = copy_cred(&clp->cl_cred, &rqstp->rq_cred);
        if (ret) {
                spin_lock(&nn->client_lock);
@@ -1355,20 +1367,9 @@ static struct nfs4_client *create_client(struct xdr_netobj name,
                spin_unlock(&nn->client_lock);
                return NULL;
        }
-       idr_init(&clp->cl_stateids);
-       atomic_set(&clp->cl_refcount, 0);
-       clp->cl_cb_state = NFSD4_CB_UNKNOWN;
-       INIT_LIST_HEAD(&clp->cl_idhash);
-       INIT_LIST_HEAD(&clp->cl_openowners);
-       INIT_LIST_HEAD(&clp->cl_delegations);
-       INIT_LIST_HEAD(&clp->cl_lru);
-       INIT_LIST_HEAD(&clp->cl_callbacks);
-       INIT_LIST_HEAD(&clp->cl_revoked);
-       spin_lock_init(&clp->cl_lock);
        nfsd4_init_callback(&clp->cl_cb_null);
        clp->cl_time = get_seconds();
        clear_bit(0, &clp->cl_cb_slot_busy);
-       rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table");
        copy_verf(clp, verf);
        rpc_copy_addr((struct sockaddr *) &clp->cl_addr, sa);
        gen_confirm(clp);
@@ -3716,9 +3717,16 @@ out:
 static __be32
 nfsd4_free_lock_stateid(struct nfs4_ol_stateid *stp)
 {
-       if (check_for_locks(stp->st_file, lockowner(stp->st_stateowner)))
+       struct nfs4_lockowner *lo = lockowner(stp->st_stateowner);
+
+       if (check_for_locks(stp->st_file, lo))
                return nfserr_locks_held;
-       release_lock_stateid(stp);
+       /*
+        * Currently there's a 1-1 lock stateid<->lockowner
+        * correspondance, and we have to delete the lockowner when we
+        * delete the lock stateid:
+        */
+       unhash_lockowner(lo);
        return nfs_ok;
 }
 
@@ -4158,6 +4166,10 @@ static bool same_lockowner_ino(struct nfs4_lockowner *lo, struct inode *inode, c
 
        if (!same_owner_str(&lo->lo_owner, owner, clid))
                return false;
+       if (list_empty(&lo->lo_owner.so_stateids)) {
+               WARN_ON_ONCE(1);
+               return false;
+       }
        lst = list_first_entry(&lo->lo_owner.so_stateids,
                               struct nfs4_ol_stateid, st_perstateowner);
        return lst->st_file->fi_inode == inode;
index 4e565c814309d2637c7d9bb8081f03a4d19216d0..732648b270dc1072f679b550fb386147e65b5db0 100644 (file)
@@ -698,6 +698,8 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
        }
        group->overflow_event = &oevent->fse;
 
+       if (force_o_largefile())
+               event_f_flags |= O_LARGEFILE;
        group->fanotify_data.f_flags = event_f_flags;
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
        spin_lock_init(&group->fanotify_data.access_lock);
index af3f7aa73e13a007d06fd528d8c8d101d2553087..ee1f88419cb0640d38203eb3a16c7b03094f7c56 100644 (file)
@@ -472,11 +472,15 @@ bail:
 
 void dlm_destroy_master_caches(void)
 {
-       if (dlm_lockname_cache)
+       if (dlm_lockname_cache) {
                kmem_cache_destroy(dlm_lockname_cache);
+               dlm_lockname_cache = NULL;
+       }
 
-       if (dlm_lockres_cache)
+       if (dlm_lockres_cache) {
                kmem_cache_destroy(dlm_lockres_cache);
+               dlm_lockres_cache = NULL;
+       }
 }
 
 static void dlm_lockres_release(struct kref *kref)
index 9e363e41dacc8c2ebc007661a598c01e84da45c9..0855f772cd41599d6c1d1091e7da616d32cccf53 100644 (file)
@@ -246,6 +246,12 @@ posix_acl_equiv_mode(const struct posix_acl *acl, umode_t *mode_p)
        umode_t mode = 0;
        int not_equiv = 0;
 
+       /*
+        * A null ACL can always be presented as mode bits.
+        */
+       if (!acl)
+               return 0;
+
        FOREACH_ACL_ENTRY(pa, acl, pe) {
                switch (pa->e_tag) {
                        case ACL_USER_OBJ:
index 9bc07d2b53cf3a0e66605912386f9d2367601585..e246954ea48cb486b1c8101e6f621364d6844535 100644 (file)
@@ -1537,7 +1537,7 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov,
        struct iovec iovstack[UIO_FASTIOV];
        struct iovec *iov = iovstack;
        struct iov_iter iter;
-       ssize_t count = 0;
+       ssize_t count;
 
        pipe = get_pipe_info(file);
        if (!pipe)
@@ -1546,8 +1546,9 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov,
        ret = rw_copy_check_uvector(READ, uiov, nr_segs,
                                    ARRAY_SIZE(iovstack), iovstack, &iov);
        if (ret <= 0)
-               return ret;
+               goto out;
 
+       count = ret;
        iov_iter_init(&iter, iov, nr_segs, count, 0);
 
        sd.len = 0;
@@ -1560,6 +1561,7 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov,
        ret = __splice_from_pipe(pipe, &sd, pipe_to_user);
        pipe_unlock(pipe);
 
+out:
        if (iov != iovstack)
                kfree(iov);
 
index 28cc1acd5439bf8caeb6d93e8bf68804ad738b1b..e9ef59b3abb1e5552cdc2a8880df37b85093d249 100644 (file)
@@ -47,12 +47,13 @@ static int sysfs_kf_seq_show(struct seq_file *sf, void *v)
        ssize_t count;
        char *buf;
 
-       /* acquire buffer and ensure that it's >= PAGE_SIZE */
+       /* acquire buffer and ensure that it's >= PAGE_SIZE and clear */
        count = seq_get_buf(sf, &buf);
        if (count < PAGE_SIZE) {
                seq_commit(sf, -1);
                return 0;
        }
+       memset(buf, 0, PAGE_SIZE);
 
        /*
         * Invoke show().  Control may reach here via seq file lseek even
index a66ad6196f59cca2f61a31c4a966d41b92497ad8..8794423f7efbe2c90408ba9dfa6cbb7e55e6c3d9 100644 (file)
@@ -63,7 +63,8 @@ int __init sysfs_init(void)
 {
        int err;
 
-       sysfs_root = kernfs_create_root(NULL, 0, NULL);
+       sysfs_root = kernfs_create_root(NULL, KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK,
+                                       NULL);
        if (IS_ERR(sysfs_root))
                return PTR_ERR(sysfs_root);
 
index a1266089eca1fc0054065dfc723e697daf5691e6..a81c7b556896115a4afbdea5452523057ccd195f 100644 (file)
@@ -1556,7 +1556,7 @@ static int ubifs_remount_rw(struct ubifs_info *c)
        if (c->space_fixup) {
                err = ubifs_fixup_free_space(c);
                if (err)
-                       return err;
+                       goto out;
        }
 
        err = check_free_space(c);
index 01b6a0102fbdd4d153612740d95c4f00fda691f7..abda1124a70f66fbd1a79b28f8eaf5bf1916da1e 100644 (file)
@@ -213,7 +213,7 @@ xfs_attr_calc_size(
                 * Out of line attribute, cannot double split, but
                 * make room for the attribute value itself.
                 */
-               uint    dblocks = XFS_B_TO_FSB(mp, valuelen);
+               uint    dblocks = xfs_attr3_rmt_blocks(mp, valuelen);
                nblks += dblocks;
                nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
        }
@@ -698,11 +698,22 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
 
                trace_xfs_attr_leaf_replace(args);
 
+               /* save the attribute state for later removal*/
                args->op_flags |= XFS_DA_OP_RENAME;     /* an atomic rename */
                args->blkno2 = args->blkno;             /* set 2nd entry info*/
                args->index2 = args->index;
                args->rmtblkno2 = args->rmtblkno;
                args->rmtblkcnt2 = args->rmtblkcnt;
+               args->rmtvaluelen2 = args->rmtvaluelen;
+
+               /*
+                * clear the remote attr state now that it is saved so that the
+                * values reflect the state of the attribute we are about to
+                * add, not the attribute we just found and will remove later.
+                */
+               args->rmtblkno = 0;
+               args->rmtblkcnt = 0;
+               args->rmtvaluelen = 0;
        }
 
        /*
@@ -794,6 +805,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                args->blkno = args->blkno2;
                args->rmtblkno = args->rmtblkno2;
                args->rmtblkcnt = args->rmtblkcnt2;
+               args->rmtvaluelen = args->rmtvaluelen2;
                if (args->rmtblkno) {
                        error = xfs_attr_rmtval_remove(args);
                        if (error)
@@ -999,13 +1011,22 @@ restart:
 
                trace_xfs_attr_node_replace(args);
 
+               /* save the attribute state for later removal*/
                args->op_flags |= XFS_DA_OP_RENAME;     /* atomic rename op */
                args->blkno2 = args->blkno;             /* set 2nd entry info*/
                args->index2 = args->index;
                args->rmtblkno2 = args->rmtblkno;
                args->rmtblkcnt2 = args->rmtblkcnt;
+               args->rmtvaluelen2 = args->rmtvaluelen;
+
+               /*
+                * clear the remote attr state now that it is saved so that the
+                * values reflect the state of the attribute we are about to
+                * add, not the attribute we just found and will remove later.
+                */
                args->rmtblkno = 0;
                args->rmtblkcnt = 0;
+               args->rmtvaluelen = 0;
        }
 
        retval = xfs_attr3_leaf_add(blk->bp, state->args);
@@ -1133,6 +1154,7 @@ restart:
                args->blkno = args->blkno2;
                args->rmtblkno = args->rmtblkno2;
                args->rmtblkcnt = args->rmtblkcnt2;
+               args->rmtvaluelen = args->rmtvaluelen2;
                if (args->rmtblkno) {
                        error = xfs_attr_rmtval_remove(args);
                        if (error)
index fe9587fab17a6822d9bec1b5862a6a133adf9dc7..511c283459b19441d782114c4f832207860deab1 100644 (file)
@@ -1229,6 +1229,7 @@ xfs_attr3_leaf_add_work(
                name_rmt->valueblk = 0;
                args->rmtblkno = 1;
                args->rmtblkcnt = xfs_attr3_rmt_blocks(mp, args->valuelen);
+               args->rmtvaluelen = args->valuelen;
        }
        xfs_trans_log_buf(args->trans, bp,
             XFS_DA_LOGRANGE(leaf, xfs_attr3_leaf_name(leaf, args->index),
@@ -2167,11 +2168,11 @@ xfs_attr3_leaf_lookup_int(
                        if (!xfs_attr_namesp_match(args->flags, entry->flags))
                                continue;
                        args->index = probe;
-                       args->valuelen = be32_to_cpu(name_rmt->valuelen);
+                       args->rmtvaluelen = be32_to_cpu(name_rmt->valuelen);
                        args->rmtblkno = be32_to_cpu(name_rmt->valueblk);
                        args->rmtblkcnt = xfs_attr3_rmt_blocks(
                                                        args->dp->i_mount,
-                                                       args->valuelen);
+                                                       args->rmtvaluelen);
                        return XFS_ERROR(EEXIST);
                }
        }
@@ -2220,19 +2221,19 @@ xfs_attr3_leaf_getvalue(
                name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index);
                ASSERT(name_rmt->namelen == args->namelen);
                ASSERT(memcmp(args->name, name_rmt->name, args->namelen) == 0);
-               valuelen = be32_to_cpu(name_rmt->valuelen);
+               args->rmtvaluelen = be32_to_cpu(name_rmt->valuelen);
                args->rmtblkno = be32_to_cpu(name_rmt->valueblk);
                args->rmtblkcnt = xfs_attr3_rmt_blocks(args->dp->i_mount,
-                                                      valuelen);
+                                                      args->rmtvaluelen);
                if (args->flags & ATTR_KERNOVAL) {
-                       args->valuelen = valuelen;
+                       args->valuelen = args->rmtvaluelen;
                        return 0;
                }
-               if (args->valuelen < valuelen) {
-                       args->valuelen = valuelen;
+               if (args->valuelen < args->rmtvaluelen) {
+                       args->valuelen = args->rmtvaluelen;
                        return XFS_ERROR(ERANGE);
                }
-               args->valuelen = valuelen;
+               args->valuelen = args->rmtvaluelen;
        }
        return 0;
 }
@@ -2519,7 +2520,7 @@ xfs_attr3_leaf_clearflag(
                ASSERT((entry->flags & XFS_ATTR_LOCAL) == 0);
                name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index);
                name_rmt->valueblk = cpu_to_be32(args->rmtblkno);
-               name_rmt->valuelen = cpu_to_be32(args->valuelen);
+               name_rmt->valuelen = cpu_to_be32(args->rmtvaluelen);
                xfs_trans_log_buf(args->trans, bp,
                         XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt)));
        }
@@ -2677,7 +2678,7 @@ xfs_attr3_leaf_flipflags(
                ASSERT((entry1->flags & XFS_ATTR_LOCAL) == 0);
                name_rmt = xfs_attr3_leaf_name_remote(leaf1, args->index);
                name_rmt->valueblk = cpu_to_be32(args->rmtblkno);
-               name_rmt->valuelen = cpu_to_be32(args->valuelen);
+               name_rmt->valuelen = cpu_to_be32(args->rmtvaluelen);
                xfs_trans_log_buf(args->trans, bp1,
                         XFS_DA_LOGRANGE(leaf1, name_rmt, sizeof(*name_rmt)));
        }
index 01db96f60cf05abf1f42e20252cdff4de0ebea0d..833fe5d98d806783ca6bb6cf2f4ecb83424bfdca 100644 (file)
@@ -447,6 +447,7 @@ xfs_attr3_leaf_list_int(
                                args.dp = context->dp;
                                args.whichfork = XFS_ATTR_FORK;
                                args.valuelen = valuelen;
+                               args.rmtvaluelen = valuelen;
                                args.value = kmem_alloc(valuelen, KM_SLEEP | KM_NOFS);
                                args.rmtblkno = be32_to_cpu(name_rmt->valueblk);
                                args.rmtblkcnt = xfs_attr3_rmt_blocks(
index 6e37823e2932aeb45d112b55010ab627adb5bde2..d2e6e948cec7be3013b853033b6e1a64b365a682 100644 (file)
@@ -337,7 +337,7 @@ xfs_attr_rmtval_get(
        struct xfs_buf          *bp;
        xfs_dablk_t             lblkno = args->rmtblkno;
        __uint8_t               *dst = args->value;
-       int                     valuelen = args->valuelen;
+       int                     valuelen;
        int                     nmap;
        int                     error;
        int                     blkcnt = args->rmtblkcnt;
@@ -347,7 +347,9 @@ xfs_attr_rmtval_get(
        trace_xfs_attr_rmtval_get(args);
 
        ASSERT(!(args->flags & ATTR_KERNOVAL));
+       ASSERT(args->rmtvaluelen == args->valuelen);
 
+       valuelen = args->rmtvaluelen;
        while (valuelen > 0) {
                nmap = ATTR_RMTVALUE_MAPSIZE;
                error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
@@ -415,7 +417,7 @@ xfs_attr_rmtval_set(
         * attributes have headers, we can't just do a straight byte to FSB
         * conversion and have to take the header space into account.
         */
-       blkcnt = xfs_attr3_rmt_blocks(mp, args->valuelen);
+       blkcnt = xfs_attr3_rmt_blocks(mp, args->rmtvaluelen);
        error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff,
                                                   XFS_ATTR_FORK);
        if (error)
@@ -480,7 +482,7 @@ xfs_attr_rmtval_set(
         */
        lblkno = args->rmtblkno;
        blkcnt = args->rmtblkcnt;
-       valuelen = args->valuelen;
+       valuelen = args->rmtvaluelen;
        while (valuelen > 0) {
                struct xfs_buf  *bp;
                xfs_daddr_t     dblkno;
index 6e95ea79f5d73aa2447fc49eb0e4c7e9bb73a25d..201c6091d26abfa2e38dd17fd960e3efcb69bcd7 100644 (file)
@@ -60,10 +60,12 @@ typedef struct xfs_da_args {
        int             index;          /* index of attr of interest in blk */
        xfs_dablk_t     rmtblkno;       /* remote attr value starting blkno */
        int             rmtblkcnt;      /* remote attr value block count */
+       int             rmtvaluelen;    /* remote attr value length in bytes */
        xfs_dablk_t     blkno2;         /* blkno of 2nd attr leaf of interest */
        int             index2;         /* index of 2nd attr in blk */
        xfs_dablk_t     rmtblkno2;      /* remote attr value starting blkno */
        int             rmtblkcnt2;     /* remote attr value block count */
+       int             rmtvaluelen2;   /* remote attr value length in bytes */
        int             op_flags;       /* operation flags */
        enum xfs_dacmp  cmpresult;      /* name compare result for lookups */
 } xfs_da_args_t;
index 1399e187d425dc7af0f8b5062afaf312fe5a0927..753e467aa1a5991d0175087284ff9cde35591c40 100644 (file)
@@ -237,7 +237,7 @@ xfs_fs_nfs_commit_metadata(
 
        if (!lsn)
                return 0;
-       return _xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, NULL);
+       return -_xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, NULL);
 }
 
 const struct export_operations xfs_export_operations = {
index 951a2321ee010f35c1d3395c09d0830d74197cfd..830c1c937b8888e7adba5557997d8d30dfc91713 100644 (file)
@@ -155,7 +155,7 @@ xfs_dir_fsync(
 
        if (!lsn)
                return 0;
-       return _xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, NULL);
+       return -_xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, NULL);
 }
 
 STATIC int
@@ -295,7 +295,7 @@ xfs_file_aio_read(
                xfs_rw_ilock(ip, XFS_IOLOCK_EXCL);
 
                if (inode->i_mapping->nrpages) {
-                       ret = -filemap_write_and_wait_range(
+                       ret = filemap_write_and_wait_range(
                                                        VFS_I(ip)->i_mapping,
                                                        pos, -1);
                        if (ret) {
@@ -837,7 +837,7 @@ xfs_file_fallocate(
                unsigned blksize_mask = (1 << inode->i_blkbits) - 1;
 
                if (offset & blksize_mask || len & blksize_mask) {
-                       error = -EINVAL;
+                       error = EINVAL;
                        goto out_unlock;
                }
 
@@ -846,7 +846,7 @@ xfs_file_fallocate(
                 * in which case it is effectively a truncate operation
                 */
                if (offset + len >= i_size_read(inode)) {
-                       error = -EINVAL;
+                       error = EINVAL;
                        goto out_unlock;
                }
 
index ef1ca010f417713358c0d0f3869189121e2f0ff0..36d630319a2784c7fe39f83fc9d66b74ee3add7b 100644 (file)
@@ -72,8 +72,8 @@ xfs_initxattrs(
        int                     error = 0;
 
        for (xattr = xattr_array; xattr->name != NULL; xattr++) {
-               error = xfs_attr_set(ip, xattr->name, xattr->value,
-                                    xattr->value_len, ATTR_SECURE);
+               error = -xfs_attr_set(ip, xattr->name, xattr->value,
+                                     xattr->value_len, ATTR_SECURE);
                if (error < 0)
                        break;
        }
@@ -93,8 +93,8 @@ xfs_init_security(
        struct inode    *dir,
        const struct qstr *qstr)
 {
-       return security_inode_init_security(inode, dir, qstr,
-                                           &xfs_initxattrs, NULL);
+       return -security_inode_init_security(inode, dir, qstr,
+                                            &xfs_initxattrs, NULL);
 }
 
 static void
@@ -124,15 +124,15 @@ xfs_cleanup_inode(
        xfs_dentry_to_name(&teardown, dentry, 0);
 
        xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
-       iput(inode);
 }
 
 STATIC int
-xfs_vn_mknod(
+xfs_generic_create(
        struct inode    *dir,
        struct dentry   *dentry,
        umode_t         mode,
-       dev_t           rdev)
+       dev_t           rdev,
+       bool            tmpfile)        /* unnamed file */
 {
        struct inode    *inode;
        struct xfs_inode *ip = NULL;
@@ -156,8 +156,12 @@ xfs_vn_mknod(
        if (error)
                return error;
 
-       xfs_dentry_to_name(&name, dentry, mode);
-       error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip);
+       if (!tmpfile) {
+               xfs_dentry_to_name(&name, dentry, mode);
+               error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip);
+       } else {
+               error = xfs_create_tmpfile(XFS_I(dir), dentry, mode, &ip);
+       }
        if (unlikely(error))
                goto out_free_acl;
 
@@ -169,18 +173,22 @@ xfs_vn_mknod(
 
 #ifdef CONFIG_XFS_POSIX_ACL
        if (default_acl) {
-               error = xfs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
+               error = -xfs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
                if (error)
                        goto out_cleanup_inode;
        }
        if (acl) {
-               error = xfs_set_acl(inode, acl, ACL_TYPE_ACCESS);
+               error = -xfs_set_acl(inode, acl, ACL_TYPE_ACCESS);
                if (error)
                        goto out_cleanup_inode;
        }
 #endif
 
-       d_instantiate(dentry, inode);
+       if (tmpfile)
+               d_tmpfile(dentry, inode);
+       else
+               d_instantiate(dentry, inode);
+
  out_free_acl:
        if (default_acl)
                posix_acl_release(default_acl);
@@ -189,10 +197,22 @@ xfs_vn_mknod(
        return -error;
 
  out_cleanup_inode:
-       xfs_cleanup_inode(dir, inode, dentry);
+       if (!tmpfile)
+               xfs_cleanup_inode(dir, inode, dentry);
+       iput(inode);
        goto out_free_acl;
 }
 
+STATIC int
+xfs_vn_mknod(
+       struct inode    *dir,
+       struct dentry   *dentry,
+       umode_t         mode,
+       dev_t           rdev)
+{
+       return xfs_generic_create(dir, dentry, mode, rdev, false);
+}
+
 STATIC int
 xfs_vn_create(
        struct inode    *dir,
@@ -353,6 +373,7 @@ xfs_vn_symlink(
 
  out_cleanup_inode:
        xfs_cleanup_inode(dir, inode, dentry);
+       iput(inode);
  out:
        return -error;
 }
@@ -1053,25 +1074,7 @@ xfs_vn_tmpfile(
        struct dentry   *dentry,
        umode_t         mode)
 {
-       int                     error;
-       struct xfs_inode        *ip;
-       struct inode            *inode;
-
-       error = xfs_create_tmpfile(XFS_I(dir), dentry, mode, &ip);
-       if (unlikely(error))
-               return -error;
-
-       inode = VFS_I(ip);
-
-       error = xfs_init_security(inode, dir, &dentry->d_name);
-       if (unlikely(error)) {
-               iput(inode);
-               return -error;
-       }
-
-       d_tmpfile(dentry, inode);
-
-       return 0;
+       return xfs_generic_create(dir, dentry, mode, 0, true);
 }
 
 static const struct inode_operations xfs_inode_operations = {
index 08624dc67317185b1e044fd7d67ef4573d941ef6..a5f8bd9899d37a811af38a616da44f66d73d399f 100644 (file)
@@ -616,11 +616,13 @@ xfs_log_mount(
        int             error = 0;
        int             min_logfsbs;
 
-       if (!(mp->m_flags & XFS_MOUNT_NORECOVERY))
-               xfs_notice(mp, "Mounting Filesystem");
-       else {
+       if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) {
+               xfs_notice(mp, "Mounting V%d Filesystem",
+                          XFS_SB_VERSION_NUM(&mp->m_sb));
+       } else {
                xfs_notice(mp,
-"Mounting filesystem in no-recovery mode.  Filesystem will be inconsistent.");
+"Mounting V%d filesystem in no-recovery mode. Filesystem will be inconsistent.",
+                          XFS_SB_VERSION_NUM(&mp->m_sb));
                ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);
        }
 
index 993cb19e7d390e03220f265e9ba97e0f0c8dc7fa..944f3d9456a8b4f6f0fe44721fe98f9f52c3bd69 100644 (file)
@@ -743,8 +743,6 @@ xfs_mountfs(
                new_size *= mp->m_sb.sb_inodesize / XFS_DINODE_MIN_SIZE;
                if (mp->m_sb.sb_inoalignmt >= XFS_B_TO_FSBT(mp, new_size))
                        mp->m_inode_cluster_size = new_size;
-               xfs_info(mp, "Using inode cluster size of %d bytes",
-                        mp->m_inode_cluster_size);
        }
 
        /*
index 348e4d2ed6e6e9621b82c535212e32093b51da0c..dc977b6e6a365a4222fb79b212f5c2b23b46b84c 100644 (file)
@@ -843,22 +843,17 @@ xfs_qm_init_quotainfo(
 
        qinf = mp->m_quotainfo = kmem_zalloc(sizeof(xfs_quotainfo_t), KM_SLEEP);
 
-       if ((error = list_lru_init(&qinf->qi_lru))) {
-               kmem_free(qinf);
-               mp->m_quotainfo = NULL;
-               return error;
-       }
+       error = -list_lru_init(&qinf->qi_lru);
+       if (error)
+               goto out_free_qinf;
 
        /*
         * See if quotainodes are setup, and if not, allocate them,
         * and change the superblock accordingly.
         */
-       if ((error = xfs_qm_init_quotainos(mp))) {
-               list_lru_destroy(&qinf->qi_lru);
-               kmem_free(qinf);
-               mp->m_quotainfo = NULL;
-               return error;
-       }
+       error = xfs_qm_init_quotainos(mp);
+       if (error)
+               goto out_free_lru;
 
        INIT_RADIX_TREE(&qinf->qi_uquota_tree, GFP_NOFS);
        INIT_RADIX_TREE(&qinf->qi_gquota_tree, GFP_NOFS);
@@ -918,7 +913,7 @@ xfs_qm_init_quotainfo(
                qinf->qi_isoftlimit = be64_to_cpu(ddqp->d_ino_softlimit);
                qinf->qi_rtbhardlimit = be64_to_cpu(ddqp->d_rtb_hardlimit);
                qinf->qi_rtbsoftlimit = be64_to_cpu(ddqp->d_rtb_softlimit);
+
                xfs_qm_dqdestroy(dqp);
        } else {
                qinf->qi_btimelimit = XFS_QM_BTIMELIMIT;
@@ -935,6 +930,13 @@ xfs_qm_init_quotainfo(
        qinf->qi_shrinker.flags = SHRINKER_NUMA_AWARE;
        register_shrinker(&qinf->qi_shrinker);
        return 0;
+
+out_free_lru:
+       list_lru_destroy(&qinf->qi_lru);
+out_free_qinf:
+       kmem_free(qinf);
+       mp->m_quotainfo = NULL;
+       return error;
 }
 
 
index 0c0e41bbe4e369d7bf5267ed906e59159a4e2ff7..8baf61afae1ddf132757caad16c359ec447dcc39 100644 (file)
@@ -201,10 +201,6 @@ xfs_mount_validate_sb(
         * write validation, we don't need to check feature masks.
         */
        if (check_version && XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) {
-               xfs_alert(mp,
-"Version 5 superblock detected. This kernel has EXPERIMENTAL support enabled!\n"
-"Use of these features in this kernel is at your own risk!");
-
                if (xfs_sb_has_compat_feature(sbp,
                                        XFS_SB_FEAT_COMPAT_UNKNOWN)) {
                        xfs_warn(mp,
index 2053767763773b60d7b7f8aca31f3b31a9219785..3494eff8e4ebfbce7256fd8d95769e2a1799619c 100644 (file)
@@ -1433,11 +1433,11 @@ xfs_fs_fill_super(
        if (error)
                goto out_free_fsname;
 
-       error = xfs_init_mount_workqueues(mp);
+       error = -xfs_init_mount_workqueues(mp);
        if (error)
                goto out_close_devices;
 
-       error = xfs_icsb_init_counters(mp);
+       error = -xfs_icsb_init_counters(mp);
        if (error)
                goto out_destroy_workqueues;
 
index b4ea8f50fc65ed409335bf37b3088dfde626d4a2..5e752b9590548448b42080151169cc7e38a1245c 100644 (file)
@@ -12,7 +12,7 @@
        [RLIMIT_CPU]            = {  RLIM_INFINITY,  RLIM_INFINITY },   \
        [RLIMIT_FSIZE]          = {  RLIM_INFINITY,  RLIM_INFINITY },   \
        [RLIMIT_DATA]           = {  RLIM_INFINITY,  RLIM_INFINITY },   \
-       [RLIMIT_STACK]          = {       _STK_LIM,   _STK_LIM_MAX },   \
+       [RLIMIT_STACK]          = {       _STK_LIM,  RLIM_INFINITY },   \
        [RLIMIT_CORE]           = {              0,  RLIM_INFINITY },   \
        [RLIMIT_RSS]            = {  RLIM_INFINITY,  RLIM_INFINITY },   \
        [RLIMIT_NPROC]          = {              0,              0 },   \
index 49376aec2fbb8a9e054b9605fd9de36e4cd39c5f..6dfd64b3a6042d34176e85f25e73ed477a7c600e 100644 (file)
        {0x1002, 0x983d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x983e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x983f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9851, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9852, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9853, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9854, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9855, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9856, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9857, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9858, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9859, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x985A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x985B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x985C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x985D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x985E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x985F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
index 940ece4934bab0e0c17f491b28da059454967621..012d58fa8ff0ebb69812e2b863e6dee6a2ae6c01 100644 (file)
        INTEL_VGA_DEVICE(0x0A06, info), /* ULT GT1 mobile */ \
        INTEL_VGA_DEVICE(0x0A16, info), /* ULT GT2 mobile */ \
        INTEL_VGA_DEVICE(0x0A26, info), /* ULT GT3 mobile */ \
-       INTEL_VGA_DEVICE(0x0A0E, info), /* ULT GT1 reserved */ \
-       INTEL_VGA_DEVICE(0x0A1E, info), /* ULT GT2 reserved */ \
+       INTEL_VGA_DEVICE(0x0A0E, info), /* ULX GT1 mobile */ \
+       INTEL_VGA_DEVICE(0x0A1E, info), /* ULX GT2 mobile */ \
        INTEL_VGA_DEVICE(0x0A2E, info), /* ULT GT3 reserved */ \
        INTEL_VGA_DEVICE(0x0D06, info), /* CRW GT1 mobile */ \
        INTEL_VGA_DEVICE(0x0D16, info), /* CRW GT2 mobile */ \
index 63b5eff0a80f647ffc0c6bdb6064ac56d482fc34..fdd7e1b61f60d7d3db83211838d6225a6091c5fc 100644 (file)
@@ -47,6 +47,7 @@ struct amba_driver {
 enum amba_vendor {
        AMBA_VENDOR_ARM = 0x41,
        AMBA_VENDOR_ST = 0x80,
+       AMBA_VENDOR_QCOM = 0x51,
 };
 
 extern struct bus_type amba_bustype;
index c2515851c1aa2038c5298c8ab3288d469cd3bb5b..d60904b9e50532410af2956c3546fa5072cae08e 100644 (file)
@@ -473,6 +473,7 @@ struct cftype {
 };
 
 extern struct cgroup_root cgrp_dfl_root;
+extern struct css_set init_css_set;
 
 static inline bool cgroup_on_dfl(const struct cgroup *cgrp)
 {
@@ -700,6 +701,20 @@ static inline struct cgroup_subsys_state *task_css(struct task_struct *task,
        return task_css_check(task, subsys_id, false);
 }
 
+/**
+ * task_css_is_root - test whether a task belongs to the root css
+ * @task: the target task
+ * @subsys_id: the target subsystem ID
+ *
+ * Test whether @task belongs to the root css on the specified subsystem.
+ * May be invoked in any context.
+ */
+static inline bool task_css_is_root(struct task_struct *task, int subsys_id)
+{
+       return task_css_check(task, subsys_id, true) ==
+               init_css_set.subsys[subsys_id];
+}
+
 static inline struct cgroup *task_cgroup(struct task_struct *task,
                                         int subsys_id)
 {
index 3b9bfdb83ba6f698cbe1ddf8409f8b6e0dc17427..3c7ec327ebd2eecc2fb63ac4f742ca0d75c56ec8 100644 (file)
@@ -221,6 +221,8 @@ struct dentry_operations {
 #define DCACHE_SYMLINK_TYPE            0x00300000 /* Symlink */
 #define DCACHE_FILE_TYPE               0x00400000 /* Other file type */
 
+#define DCACHE_MAY_FREE                        0x00800000
+
 extern seqlock_t rename_lock;
 
 static inline int dname_external(const struct dentry *dentry)
index 8300fb87b84ac1329d8facb1d560767c29c549d8..72cb0ddb9678d21eb2f2edd20a36b594b72160d9 100644 (file)
@@ -429,6 +429,7 @@ typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
 typedef void (*dma_async_tx_callback)(void *dma_async_param);
 
 struct dmaengine_unmap_data {
+       u8 map_cnt;
        u8 to_cnt;
        u8 from_cnt;
        u8 bidi_cnt;
index bed128e8f4b10c318ff6439933b04dc0845660f9..05e53ccb708b390b7a1f7afb01682fd65046eb3c 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __LINUX_GPIO_CONSUMER_H
 #define __LINUX_GPIO_CONSUMER_H
 
+#include <linux/bug.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
 
@@ -23,6 +24,12 @@ struct gpio_desc *__must_check gpiod_get(struct device *dev,
 struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
                                               const char *con_id,
                                               unsigned int idx);
+struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
+                                                 const char *con_id);
+struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev,
+                                                       const char *con_id,
+                                                       unsigned int index);
+
 void gpiod_put(struct gpio_desc *desc);
 
 struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
@@ -30,6 +37,12 @@ struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
 struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
                                                    const char *con_id,
                                                    unsigned int idx);
+struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
+                                                      const char *con_id);
+struct gpio_desc *__must_check
+devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
+                             unsigned int index);
+
 void devm_gpiod_put(struct device *dev, struct gpio_desc *desc);
 
 int gpiod_get_direction(const struct gpio_desc *desc);
@@ -73,6 +86,20 @@ static inline struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
 {
        return ERR_PTR(-ENOSYS);
 }
+
+static inline struct gpio_desc *__must_check
+gpiod_get_optional(struct device *dev, const char *con_id)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
+static inline struct gpio_desc *__must_check
+gpiod_get_index_optional(struct device *dev, const char *con_id,
+                        unsigned int index)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
 static inline void gpiod_put(struct gpio_desc *desc)
 {
        might_sleep();
@@ -93,6 +120,20 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
 {
        return ERR_PTR(-ENOSYS);
 }
+
+static inline struct gpio_desc *__must_check
+devm_gpiod_get_optional(struct device *dev, const char *con_id)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
+static inline struct gpio_desc *__must_check
+devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
+                             unsigned int index)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
 static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
 {
        might_sleep();
index 1827b43966d96b75c378ba21025c9d94062d9fd0..573e4f3243d0527ae95c5dec90ef02694346ab82 100644 (file)
@@ -51,7 +51,10 @@ struct seq_file;
  *      format specifier for an unsigned int.  It is substituted by the actual
  *      number of the gpio.
  * @can_sleep: flag must be set iff get()/set() methods sleep, as they
- *     must while accessing GPIO expander chips over I2C or SPI
+ *     must while accessing GPIO expander chips over I2C or SPI. This
+ *     implies that if the chip supports IRQs, these IRQs need to be threaded
+ *     as the chip access may sleep when e.g. reading out the IRQ status
+ *     registers.
  * @exported: flags if the gpiochip is exported for use from sysfs. Private.
  *
  * A gpio_chip can help platforms abstract various sources of GPIOs so
index 5b337cf8fb8655755fd00360df587745e8cc34f6..b65166de1d9d1f754f787aa1f58444e9d3da4ff0 100644 (file)
@@ -412,6 +412,16 @@ static inline spinlock_t *huge_pte_lockptr(struct hstate *h,
        return &mm->page_table_lock;
 }
 
+static inline bool hugepages_supported(void)
+{
+       /*
+        * Some platform decide whether they support huge pages at boot
+        * time. On these, such as powerpc, HPAGE_SHIFT is set to 0 when
+        * there is no such support
+        */
+       return HPAGE_SHIFT != 0;
+}
+
 #else  /* CONFIG_HUGETLB_PAGE */
 struct hstate {};
 #define alloc_huge_page_node(h, nid) NULL
index 7c8b20b120eac680f27e3cd1e99630b1fe521799..a9a53b12397b0c4fd29a11cbf5f9cbbd18944fd8 100644 (file)
@@ -56,6 +56,7 @@ struct macvlan_dev {
        int                     numqueues;
        netdev_features_t       tap_features;
        int                     minor;
+       int                     nest_level;
 };
 
 static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
index 13bbbde00e68de454c8cf30f0581796d55eb0a40..b2acc4a1b13c9bd906869bc52d501f53f67d3c87 100644 (file)
@@ -73,7 +73,7 @@ static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb)
 /* found in socket.c */
 extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *));
 
-static inline int is_vlan_dev(struct net_device *dev)
+static inline bool is_vlan_dev(struct net_device *dev)
 {
         return dev->priv_flags & IFF_802_1Q_VLAN;
 }
@@ -159,6 +159,7 @@ struct vlan_dev_priv {
 #ifdef CONFIG_NET_POLL_CONTROLLER
        struct netpoll                          *netpoll;
 #endif
+       unsigned int                            nest_level;
 };
 
 static inline struct vlan_dev_priv *vlan_dev_priv(const struct net_device *dev)
@@ -197,6 +198,12 @@ extern void vlan_vids_del_by_dev(struct net_device *dev,
                                 const struct net_device *by_dev);
 
 extern bool vlan_uses_dev(const struct net_device *dev);
+
+static inline int vlan_get_encap_level(struct net_device *dev)
+{
+       BUG_ON(!is_vlan_dev(dev));
+       return vlan_dev_priv(dev)->nest_level;
+}
 #else
 static inline struct net_device *
 __vlan_find_dev_deep(struct net_device *real_dev,
@@ -263,6 +270,11 @@ static inline bool vlan_uses_dev(const struct net_device *dev)
 {
        return false;
 }
+static inline int vlan_get_encap_level(struct net_device *dev)
+{
+       BUG();
+       return 0;
+}
 #endif
 
 static inline bool vlan_hw_offload_capable(netdev_features_t features,
@@ -483,4 +495,5 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb,
                 */
                skb->protocol = htons(ETH_P_802_2);
 }
+
 #endif /* !(_LINUX_IF_VLAN_H_) */
index 97ac926c78a707fb6bf45293d00e8f4d86515f43..051c85032f481ae8fa1fb5ca6542df83588a9153 100644 (file)
@@ -272,6 +272,11 @@ static inline int irq_set_affinity(unsigned int irq, const struct cpumask *m)
        return -EINVAL;
 }
 
+static inline int irq_force_affinity(unsigned int irq, const struct cpumask *cpumask)
+{
+       return 0;
+}
+
 static inline int irq_can_set_affinity(unsigned int irq)
 {
        return 0;
index b0122dc6f96a0a21324f86b5a28c725ac3ea74cf..ca1be5c9136c4557de511143b4c9b36e1eec3734 100644 (file)
@@ -50,7 +50,24 @@ enum kernfs_node_flag {
 
 /* @flags for kernfs_create_root() */
 enum kernfs_root_flag {
-       KERNFS_ROOT_CREATE_DEACTIVATED = 0x0001,
+       /*
+        * kernfs_nodes are created in the deactivated state and invisible.
+        * They require explicit kernfs_activate() to become visible.  This
+        * can be used to make related nodes become visible atomically
+        * after all nodes are created successfully.
+        */
+       KERNFS_ROOT_CREATE_DEACTIVATED          = 0x0001,
+
+       /*
+        * For regular flies, if the opener has CAP_DAC_OVERRIDE, open(2)
+        * succeeds regardless of the RW permissions.  sysfs had an extra
+        * layer of enforcement where open(2) fails with -EACCES regardless
+        * of CAP_DAC_OVERRIDE if the permission doesn't have the
+        * respective read or write access at all (none of S_IRUGO or
+        * S_IWUGO) or the respective operation isn't implemented.  The
+        * following flag enables that behavior.
+        */
+       KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK       = 0x0002,
 };
 
 /* type-specific structures for kernfs_node union members */
index 34a513a2727bbe83adff047613a1ad3458684ac2..a6a42dd024661324dbeed5b9cfaa028744bae154 100644 (file)
@@ -12,9 +12,9 @@
 #endif
 
 #ifdef __cplusplus
-#define CPP_ASMLINKAGE extern "C" __visible
+#define CPP_ASMLINKAGE extern "C"
 #else
-#define CPP_ASMLINKAGE __visible
+#define CPP_ASMLINKAGE
 #endif
 
 #ifndef asmlinkage
index 7c36cc55d2c79b8fe90cdec3898751ac4988165f..443176ee1ab04e1f9d2788b51d700eb2a913610c 100644 (file)
@@ -45,7 +45,6 @@ struct platform_device;
 struct rtsx_slot {
        struct platform_device  *p_dev;
        void                    (*card_event)(struct platform_device *p_dev);
-       void                    (*done_transfer)(struct platform_device *p_dev);
 };
 
 #endif
index 8d6bbd609ad9b6142357b0203bf7e0250e923ae4..a3835976f7c639e8f24e17cf2df6dc495f07fae4 100644 (file)
@@ -943,12 +943,6 @@ void rtsx_pci_send_cmd_no_wait(struct rtsx_pcr *pcr);
 int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout);
 int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
                int num_sg, bool read, int timeout);
-int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
-               int num_sg, bool read);
-int rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
-               int num_sg, bool read);
-int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist,
-               int sg_count, bool read);
 int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len);
 int rtsx_pci_write_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len);
 int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card);
index 6b8e1ff4672b0a39aeef85604a106e93c5984730..e6088c2e2092f0db394940d0a91802de5297c01c 100644 (file)
@@ -111,7 +111,6 @@ enum tx3589x_block {
 #define TC3589x_INT_PORIRQ     7
 
 #define TC3589x_NR_INTERNAL_IRQS       8
-#define TC3589x_INT_GPIO(x)    (TC3589x_NR_INTERNAL_IRQS + (x))
 
 struct tc3589x {
        struct mutex lock;
index b66e7610d4eec9f4d67e5f8bbd745bb6cbd3c99a..7040dc98ff8baa59118cd42dd728d3152afb7c86 100644 (file)
@@ -421,6 +421,17 @@ struct mlx4_wqe_inline_seg {
        __be32                  byte_count;
 };
 
+enum mlx4_update_qp_attr {
+       MLX4_UPDATE_QP_SMAC             = 1 << 0,
+};
+
+struct mlx4_update_qp_params {
+       u8      smac_index;
+};
+
+int mlx4_update_qp(struct mlx4_dev *dev, struct mlx4_qp *qp,
+                  enum mlx4_update_qp_attr attr,
+                  struct mlx4_update_qp_params *params);
 int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
                   enum mlx4_qp_state cur_state, enum mlx4_qp_state new_state,
                   struct mlx4_qp_context *context, enum mlx4_qp_optpar optpar,
index bf9811e1321a5ae80eceeba7664f7d677da9648e..d6777060449fc633df907744a0237152ef9f8c4b 100644 (file)
@@ -370,6 +370,8 @@ static inline int is_vmalloc_or_module_addr(const void *x)
 }
 #endif
 
+extern void kvfree(const void *addr);
+
 static inline void compound_lock(struct page *page)
 {
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
index 94734a6259a4d9ee36e25b342c86d3c1bf9d5fcf..17d83393afcc4337d50f00cfa837030d9429c6f8 100644 (file)
@@ -248,24 +248,17 @@ do {                                                              \
 bool __net_get_random_once(void *buf, int nbytes, bool *done,
                           struct static_key *done_key);
 
-#ifdef HAVE_JUMP_LABEL
-#define ___NET_RANDOM_STATIC_KEY_INIT ((struct static_key) \
-               { .enabled = ATOMIC_INIT(0), .entries = (void *)1 })
-#else /* !HAVE_JUMP_LABEL */
-#define ___NET_RANDOM_STATIC_KEY_INIT STATIC_KEY_INIT_FALSE
-#endif /* HAVE_JUMP_LABEL */
-
 #define net_get_random_once(buf, nbytes)                               \
        ({                                                              \
                bool ___ret = false;                                    \
                static bool ___done = false;                            \
-               static struct static_key ___done_key =                  \
-                       ___NET_RANDOM_STATIC_KEY_INIT;                  \
-               if (!static_key_true(&___done_key))                     \
+               static struct static_key ___once_key =                  \
+                       STATIC_KEY_INIT_TRUE;                           \
+               if (static_key_true(&___once_key))                      \
                        ___ret = __net_get_random_once(buf,             \
                                                       nbytes,          \
                                                       &___done,        \
-                                                      &___done_key);   \
+                                                      &___once_key);   \
                ___ret;                                                 \
        })
 
index 7ed3a3aa6604b7b8511ea709ea2c2312a1d38bb2..b42d07b0390b2e95c3e551bb6639b906472bf70b 100644 (file)
@@ -1144,6 +1144,7 @@ struct net_device_ops {
        netdev_tx_t             (*ndo_dfwd_start_xmit) (struct sk_buff *skb,
                                                        struct net_device *dev,
                                                        void *priv);
+       int                     (*ndo_get_lock_subclass)(struct net_device *dev);
 };
 
 /**
@@ -2950,7 +2951,12 @@ static inline void netif_addr_lock(struct net_device *dev)
 
 static inline void netif_addr_lock_nested(struct net_device *dev)
 {
-       spin_lock_nested(&dev->addr_list_lock, SINGLE_DEPTH_NESTING);
+       int subclass = SINGLE_DEPTH_NESTING;
+
+       if (dev->netdev_ops->ndo_get_lock_subclass)
+               subclass = dev->netdev_ops->ndo_get_lock_subclass(dev);
+
+       spin_lock_nested(&dev->addr_list_lock, subclass);
 }
 
 static inline void netif_addr_lock_bh(struct net_device *dev)
@@ -3050,9 +3056,18 @@ extern int               weight_p;
 extern int             bpf_jit_enable;
 
 bool netdev_has_upper_dev(struct net_device *dev, struct net_device *upper_dev);
+struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
+                                                    struct list_head **iter);
 struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
                                                     struct list_head **iter);
 
+/* iterate through upper list, must be called under RCU read lock */
+#define netdev_for_each_upper_dev_rcu(dev, updev, iter) \
+       for (iter = &(dev)->adj_list.upper, \
+            updev = netdev_upper_get_next_dev_rcu(dev, &(iter)); \
+            updev; \
+            updev = netdev_upper_get_next_dev_rcu(dev, &(iter)))
+
 /* iterate through upper list, must be called under RCU read lock */
 #define netdev_for_each_all_upper_dev_rcu(dev, updev, iter) \
        for (iter = &(dev)->all_adj_list.upper, \
@@ -3077,6 +3092,14 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev,
             priv; \
             priv = netdev_lower_get_next_private_rcu(dev, &(iter)))
 
+void *netdev_lower_get_next(struct net_device *dev,
+                               struct list_head **iter);
+#define netdev_for_each_lower_dev(dev, ldev, iter) \
+       for (iter = &(dev)->adj_list.lower, \
+            ldev = netdev_lower_get_next(dev, &(iter)); \
+            ldev; \
+            ldev = netdev_lower_get_next(dev, &(iter)))
+
 void *netdev_adjacent_get_private(struct list_head *adj_list);
 void *netdev_lower_get_first_private_rcu(struct net_device *dev);
 struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
@@ -3092,6 +3115,8 @@ void netdev_upper_dev_unlink(struct net_device *dev,
 void netdev_adjacent_rename_links(struct net_device *dev, char *oldname);
 void *netdev_lower_dev_get_private(struct net_device *dev,
                                   struct net_device *lower_dev);
+int dev_get_nest_level(struct net_device *dev,
+                      bool (*type_check)(struct net_device *dev));
 int skb_checksum_help(struct sk_buff *skb);
 struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
                                  netdev_features_t features, bool tx_path);
@@ -3180,12 +3205,7 @@ void netdev_change_features(struct net_device *dev);
 void netif_stacked_transfer_operstate(const struct net_device *rootdev,
                                        struct net_device *dev);
 
-netdev_features_t netif_skb_dev_features(struct sk_buff *skb,
-                                        const struct net_device *dev);
-static inline netdev_features_t netif_skb_features(struct sk_buff *skb)
-{
-       return netif_skb_dev_features(skb, skb->dev);
-}
+netdev_features_t netif_skb_features(struct sk_buff *skb);
 
 static inline bool net_gso_ok(netdev_features_t features, int gso_type)
 {
index aad8eeaf416d4bbf6d7ae6a4b40a27d4c346f1c4..f64b01787ddc273a8a48eecf1b3801ffa8154f0d 100644 (file)
@@ -169,4 +169,11 @@ struct netlink_tap {
 extern int netlink_add_tap(struct netlink_tap *nt);
 extern int netlink_remove_tap(struct netlink_tap *nt);
 
+bool __netlink_ns_capable(const struct netlink_skb_parms *nsp,
+                         struct user_namespace *ns, int cap);
+bool netlink_ns_capable(const struct sk_buff *skb,
+                       struct user_namespace *ns, int cap);
+bool netlink_capable(const struct sk_buff *skb, int cap);
+bool netlink_net_capable(const struct sk_buff *skb, int cap);
+
 #endif /* __LINUX_NETLINK_H */
index 3bad8d106e0ea01b2ae7524e216c83b4e654ced3..e6f0988c1c68a18dbc96c804d5d1c01c0aa6d9fb 100644 (file)
@@ -349,7 +349,7 @@ int of_device_is_stdout_path(struct device_node *dn);
 
 #else /* CONFIG_OF */
 
-static inline const char* of_node_full_name(struct device_node *np)
+static inline const char* of_node_full_name(const struct device_node *np)
 {
        return "<no-node>";
 }
index f14123a5a9df2b90d6ac0fccba8ce8b227059055..38fc05036015d7538df934cc8d4e94e1c5f10e86 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/errno.h>
 #include <linux/gpio.h>
 #include <linux/of.h>
-#include <linux/gpio/consumer.h>
 
 struct device_node;
 
@@ -48,7 +47,7 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc)
        return container_of(gc, struct of_mm_gpio_chip, gc);
 }
 
-extern struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
+extern int of_get_named_gpio_flags(struct device_node *np,
                const char *list_name, int index, enum of_gpio_flags *flags);
 
 extern int of_mm_gpiochip_add(struct device_node *np,
@@ -63,10 +62,10 @@ extern int of_gpio_simple_xlate(struct gpio_chip *gc,
 #else /* CONFIG_OF_GPIO */
 
 /* Drivers may not strictly depend on the GPIO support, so let them link. */
-static inline struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
+static inline int of_get_named_gpio_flags(struct device_node *np,
                const char *list_name, int index, enum of_gpio_flags *flags)
 {
-       return ERR_PTR(-ENOSYS);
+       return -ENOSYS;
 }
 
 static inline int of_gpio_simple_xlate(struct gpio_chip *gc,
@@ -81,18 +80,6 @@ static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
 
 #endif /* CONFIG_OF_GPIO */
 
-static inline int of_get_named_gpio_flags(struct device_node *np,
-               const char *list_name, int index, enum of_gpio_flags *flags)
-{
-       struct gpio_desc *desc;
-       desc = of_get_named_gpiod_flags(np, list_name, index, flags);
-
-       if (IS_ERR(desc))
-               return PTR_ERR(desc);
-       else
-               return desc_to_gpio(desc);
-}
-
 /**
  * of_gpio_named_count() - Count GPIOs for a device
  * @np:                device node to count GPIOs for
@@ -129,22 +116,6 @@ static inline int of_gpio_count(struct device_node *np)
        return of_gpio_named_count(np, "gpios");
 }
 
-/**
- * of_get_gpiod_flags() - Get a GPIO descriptor and flags to use with GPIO API
- * @np:                device node to get GPIO from
- * @index:     index of the GPIO
- * @flags:     a flags pointer to fill in
- *
- * Returns GPIO descriptor to use with Linux generic GPIO API, or a errno
- * value on the error condition. If @flags is not NULL the function also fills
- * in flags for the GPIO.
- */
-static inline struct gpio_desc *of_get_gpiod_flags(struct device_node *np,
-                                       int index, enum of_gpio_flags *flags)
-{
-       return of_get_named_gpiod_flags(np, "gpios", index, flags);
-}
-
 static inline int of_get_gpio_flags(struct device_node *np, int index,
                      enum of_gpio_flags *flags)
 {
index 6fe8464ed767f0dac6481a6ffc7b39ecaebdd648..881a7c3571f4617b99e0845995800d98eb4f9349 100644 (file)
@@ -31,7 +31,12 @@ extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np);
 #else /* CONFIG_OF */
 static inline int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 {
-       return -ENOSYS;
+       /*
+        * Fall back to the non-DT function to register a bus.
+        * This way, we don't have to keep compat bits around in drivers.
+        */
+
+       return mdiobus_register(mdio);
 }
 
 static inline struct phy_device *of_phy_find_device(struct device_node *phy_np)
index 41a13e70f41f5ade5228404ec6557ea2be7d113c..7944cdc27bed63df0f8b9cde11f1611af2fdd859 100644 (file)
@@ -10,7 +10,7 @@
 
 struct dma_chan;
 
-#if defined(CONFIG_DMA_OMAP) || defined(CONFIG_DMA_OMAP_MODULE)
+#if defined(CONFIG_DMA_OMAP) || (defined(CONFIG_DMA_OMAP_MODULE) && defined(MODULE))
 bool omap_dma_filter_fn(struct dma_chan *, void *);
 #else
 static inline bool omap_dma_filter_fn(struct dma_chan *c, void *d)
index 3356abcfff184e707eccb08d6f99042a8fd51acc..3ef6ea12806a297107ff65b2ad554f5176c8e301 100644 (file)
@@ -402,6 +402,8 @@ struct perf_event {
 
        struct ring_buffer              *rb;
        struct list_head                rb_entry;
+       unsigned long                   rcu_batches;
+       int                             rcu_pending;
 
        /* poll related */
        wait_queue_head_t               waitq;
index 8e3e66ac0a5215d221042e15e631fb2fe2fb51d1..953937ea5233c770d631bf3ae59be60b72630d88 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <linux/mutex.h>
 #include <linux/netdevice.h>
+#include <linux/wait.h>
 #include <uapi/linux/rtnetlink.h>
 
 extern int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, u32 group, int echo);
@@ -22,6 +23,10 @@ extern void rtnl_lock(void);
 extern void rtnl_unlock(void);
 extern int rtnl_trylock(void);
 extern int rtnl_is_locked(void);
+
+extern wait_queue_head_t netdev_unregistering_wq;
+extern struct mutex net_mutex;
+
 #ifdef CONFIG_PROVE_LOCKING
 extern int lockdep_rtnl_is_held(void);
 #else
index 25f54c79f75772a9f133c585e17a2d8e4a59e8ac..221b2bde372363765b5328638bf9320d9c95f5fd 100644 (file)
@@ -220,7 +220,7 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq);
 #define TASK_PARKED            512
 #define TASK_STATE_MAX         1024
 
-#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKWP"
+#define TASK_STATE_TO_CHAR_STR "RSDTtXZxKWP"
 
 extern char ___assert_task_state[1 - 2*!!(
                sizeof(TASK_STATE_TO_CHAR_STR)-1 != ilog2(TASK_STATE_MAX)+1)];
@@ -1153,9 +1153,12 @@ struct sched_dl_entity {
         *
         * @dl_boosted tells if we are boosted due to DI. If so we are
         * outside bandwidth enforcement mechanism (but only until we
-        * exit the critical section).
+        * exit the critical section);
+        *
+        * @dl_yielded tells if task gave up the cpu before consuming
+        * all its available runtime during the last job.
         */
-       int dl_throttled, dl_new, dl_boosted;
+       int dl_throttled, dl_new, dl_boosted, dl_yielded;
 
        /*
         * Bandwidth enforcement timer. Each -deadline task has its
index f2f7398848cfed2b348222aae7573ad2c2a76ba8..d82abd40a3c061745e94385b1c43e498004a60e8 100644 (file)
@@ -101,4 +101,13 @@ struct kmem_cache {
        struct kmem_cache_node *node[MAX_NUMNODES];
 };
 
+#ifdef CONFIG_SYSFS
+#define SLAB_SUPPORTS_SYSFS
+void sysfs_slab_remove(struct kmem_cache *);
+#else
+static inline void sysfs_slab_remove(struct kmem_cache *s)
+{
+}
+#endif
+
 #endif /* _LINUX_SLUB_DEF_H */
index 54f91d35e5fd76f13b94d8297b10be6642e07887..46cca4c06848346ca84753ac182526a4514ff277 100644 (file)
@@ -23,7 +23,7 @@ int sock_diag_check_cookie(void *sk, __u32 *cookie);
 void sock_diag_save_cookie(void *sk, __u32 *cookie);
 
 int sock_diag_put_meminfo(struct sock *sk, struct sk_buff *skb, int attr);
-int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk,
+int sock_diag_put_filterinfo(bool may_report_filterinfo, struct sock *sk,
                             struct sk_buff *skb, int attrtype);
 
 #endif
index 036cccd80d9ffa0c6c1a356fff4a53418643b7ae..1c3316a47d7e0386d1ede163c4f795275efc8130 100644 (file)
@@ -61,7 +61,6 @@ struct tty_bufhead {
        struct tty_buffer *head;        /* Queue head */
        struct work_struct work;
        struct mutex       lock;
-       spinlock_t         flush_lock;
        atomic_t           priority;
        struct tty_buffer sentinel;
        struct llist_head free;         /* Free queue head */
index 7d64d3609ec97ea76751009e82d43c38a10ab5d8..4282778694006034bccca4ce3fbeba9be29537ec 100644 (file)
@@ -155,7 +155,11 @@ struct vsock_transport {
 
 /**** CORE ****/
 
-int vsock_core_init(const struct vsock_transport *t);
+int __vsock_core_init(const struct vsock_transport *t, struct module *owner);
+static inline int vsock_core_init(const struct vsock_transport *t)
+{
+       return __vsock_core_init(t, THIS_MODULE);
+}
 void vsock_core_exit(void);
 
 /**** UTILS ****/
index f3539a15c41103b743c0571913fbb93dc402f40a..f856e5a746fae66e2c91357cfe94fc89d0acae18 100644 (file)
@@ -3668,6 +3668,18 @@ void cfg80211_sched_scan_results(struct wiphy *wiphy);
  */
 void cfg80211_sched_scan_stopped(struct wiphy *wiphy);
 
+/**
+ * cfg80211_sched_scan_stopped_rtnl - notify that the scheduled scan has stopped
+ *
+ * @wiphy: the wiphy on which the scheduled scan stopped
+ *
+ * The driver can call this function to inform cfg80211 that the
+ * scheduled scan had to be stopped, for whatever reason.  The driver
+ * is then called back via the sched_scan_stop operation when done.
+ * This function should be called with rtnl locked.
+ */
+void cfg80211_sched_scan_stopped_rtnl(struct wiphy *wiphy);
+
 /**
  * cfg80211_inform_bss_width_frame - inform cfg80211 of a received BSS frame
  *
index 6c4f5eac98e7be133af4b868507f0d217ac05c1b..216cecce65e9e1200cd760de64c27ac852ffc85b 100644 (file)
@@ -127,6 +127,7 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg);
 void rt6_ifdown(struct net *net, struct net_device *dev);
 void rt6_mtu_change(struct net_device *dev, unsigned int mtu);
 void rt6_remove_prefsrc(struct inet6_ifaddr *ifp);
+void rt6_clean_tohost(struct net *net, struct in6_addr *gateway);
 
 
 /*
index 80f500a29498e1fc9b8892e5c66be6bd02362eaa..b2704fd0ec80d714bc9e7dd9b87721da1853173c 100644 (file)
@@ -20,6 +20,11 @@ struct local_ports {
        int             range[2];
 };
 
+struct ping_group_range {
+       seqlock_t       lock;
+       kgid_t          range[2];
+};
+
 struct netns_ipv4 {
 #ifdef CONFIG_SYSCTL
        struct ctl_table_header *forw_hdr;
@@ -66,13 +71,13 @@ struct netns_ipv4 {
        int sysctl_icmp_ratemask;
        int sysctl_icmp_errors_use_inbound_ifaddr;
 
-       struct local_ports sysctl_local_ports;
+       struct local_ports ip_local_ports;
 
        int sysctl_tcp_ecn;
        int sysctl_ip_no_pmtu_disc;
        int sysctl_ip_fwd_use_pmtu;
 
-       kgid_t sysctl_ping_group_range[2];
+       struct ping_group_range ping_group_range;
 
        atomic_t dev_addr_genid;
 
index 8338a14e48053d853a57af674f7edca1e085fdc5..21569cf456ed54459a537e5a6cf02349a2a8413c 100644 (file)
@@ -2255,6 +2255,11 @@ int sock_get_timestampns(struct sock *, struct timespec __user *);
 int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len, int level,
                       int type);
 
+bool sk_ns_capable(const struct sock *sk,
+                  struct user_namespace *user_ns, int cap);
+bool sk_capable(const struct sock *sk, int cap);
+bool sk_net_capable(const struct sock *sk, int cap);
+
 /*
  *     Enable debug/info messages
  */
index ed0b2c599a64f7d701117bf54ba6a4dcd56edb31..7c5cbfe3fc49d6761bccc004c9475b16fc2a3dbe 100644 (file)
@@ -80,7 +80,7 @@ DECLARE_EVENT_CLASS(module_refcnt,
 
        TP_fast_assign(
                __entry->ip     = ip;
-               __entry->refcnt = __this_cpu_read(mod->refptr->incs) + __this_cpu_read(mod->refptr->decs);
+               __entry->refcnt = __this_cpu_read(mod->refptr->incs) - __this_cpu_read(mod->refptr->decs);
                __assign_str(name, mod->name);
        ),
 
index f863428796d532a42df39e45527da2f8c6eb9c88..c6d10af50123e1c5810aff634400e8c273949221 100644 (file)
 # define RLIM_INFINITY         (~0UL)
 #endif
 
-/*
- * RLIMIT_STACK default maximum - some architectures override it:
- */
-#ifndef _STK_LIM_MAX
-# define _STK_LIM_MAX          RLIM_INFINITY
-#endif
-
 
 #endif /* _UAPI_ASM_GENERIC_RESOURCE_H */
index 6db66783d268d9a286a86b836c9277bd89f5ac13..3336406080874bf2bd06cb1f0563aea6d8e56650 100644 (file)
@@ -697,9 +697,11 @@ __SYSCALL(__NR_finit_module, sys_finit_module)
 __SYSCALL(__NR_sched_setattr, sys_sched_setattr)
 #define __NR_sched_getattr 275
 __SYSCALL(__NR_sched_getattr, sys_sched_getattr)
+#define __NR_renameat2 276
+__SYSCALL(__NR_renameat2, sys_renameat2)
 
 #undef __NR_syscalls
-#define __NR_syscalls 276
+#define __NR_syscalls 277
 
 /*
  * All syscalls below here should go away really,
index 11917f747cb401be5b7dc8ab788fa5d0d4e8e47c..4c31a366be1639f08d2487309ff8602e4f7f4704 100644 (file)
@@ -331,9 +331,17 @@ enum {
 #define AUDIT_FAIL_PRINTK      1
 #define AUDIT_FAIL_PANIC       2
 
+/*
+ * These bits disambiguate different calling conventions that share an
+ * ELF machine type, bitness, and endianness
+ */
+#define __AUDIT_ARCH_CONVENTION_MASK 0x30000000
+#define __AUDIT_ARCH_CONVENTION_MIPS64_N32 0x20000000
+
 /* distinguish syscall tables */
 #define __AUDIT_ARCH_64BIT 0x80000000
 #define __AUDIT_ARCH_LE           0x40000000
+
 #define AUDIT_ARCH_ALPHA       (EM_ALPHA|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
 #define AUDIT_ARCH_ARM         (EM_ARM|__AUDIT_ARCH_LE)
 #define AUDIT_ARCH_ARMEB       (EM_ARM)
@@ -346,7 +354,11 @@ enum {
 #define AUDIT_ARCH_MIPS                (EM_MIPS)
 #define AUDIT_ARCH_MIPSEL      (EM_MIPS|__AUDIT_ARCH_LE)
 #define AUDIT_ARCH_MIPS64      (EM_MIPS|__AUDIT_ARCH_64BIT)
+#define AUDIT_ARCH_MIPS64N32   (EM_MIPS|__AUDIT_ARCH_64BIT|\
+                                __AUDIT_ARCH_CONVENTION_MIPS64_N32)
 #define AUDIT_ARCH_MIPSEL64    (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
+#define AUDIT_ARCH_MIPSEL64N32 (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE|\
+                                __AUDIT_ARCH_CONVENTION_MIPS64_N32)
 #define AUDIT_ARCH_OPENRISC    (EM_OPENRISC)
 #define AUDIT_ARCH_PARISC      (EM_PARISC)
 #define AUDIT_ARCH_PARISC64    (EM_PARISC|__AUDIT_ARCH_64BIT)
index cf4750e1bb4971d03a0e870d323aa3f53c683ba9..40b5ca8a1b1f3028e5e03c5b3372f98e39437422 100644 (file)
  *
  * 7.23
  *  - add FUSE_WRITEBACK_CACHE
+ *  - add time_gran to fuse_init_out
+ *  - add reserved space to fuse_init_out
+ *  - add FATTR_CTIME
+ *  - add ctime and ctimensec to fuse_setattr_in
+ *  - add FUSE_RENAME2 request
  */
 
 #ifndef _LINUX_FUSE_H
@@ -191,6 +196,7 @@ struct fuse_file_lock {
 #define FATTR_ATIME_NOW        (1 << 7)
 #define FATTR_MTIME_NOW        (1 << 8)
 #define FATTR_LOCKOWNER        (1 << 9)
+#define FATTR_CTIME    (1 << 10)
 
 /**
  * Flags returned by the OPEN request
@@ -348,6 +354,7 @@ enum fuse_opcode {
        FUSE_BATCH_FORGET  = 42,
        FUSE_FALLOCATE     = 43,
        FUSE_READDIRPLUS   = 44,
+       FUSE_RENAME2       = 45,
 
        /* CUSE specific operations */
        CUSE_INIT          = 4096,
@@ -426,6 +433,12 @@ struct fuse_rename_in {
        uint64_t        newdir;
 };
 
+struct fuse_rename2_in {
+       uint64_t        newdir;
+       uint32_t        flags;
+       uint32_t        padding;
+};
+
 struct fuse_link_in {
        uint64_t        oldnodeid;
 };
@@ -438,10 +451,10 @@ struct fuse_setattr_in {
        uint64_t        lock_owner;
        uint64_t        atime;
        uint64_t        mtime;
-       uint64_t        unused2;
+       uint64_t        ctime;
        uint32_t        atimensec;
        uint32_t        mtimensec;
-       uint32_t        unused3;
+       uint32_t        ctimensec;
        uint32_t        mode;
        uint32_t        unused4;
        uint32_t        uid;
@@ -559,6 +572,9 @@ struct fuse_init_in {
        uint32_t        flags;
 };
 
+#define FUSE_COMPAT_INIT_OUT_SIZE 8
+#define FUSE_COMPAT_22_INIT_OUT_SIZE 24
+
 struct fuse_init_out {
        uint32_t        major;
        uint32_t        minor;
@@ -567,6 +583,8 @@ struct fuse_init_out {
        uint16_t        max_background;
        uint16_t        congestion_threshold;
        uint32_t        max_write;
+       uint32_t        time_gran;
+       uint32_t        unused[9];
 };
 
 #define CUSE_INIT_INFO_MAX 4096
index 1ba9d626aa833db91c462560f27054b30e91939d..194c1eab04d8ad9cb37ae855d8c011d48722c829 100644 (file)
@@ -3856,6 +3856,8 @@ enum nl80211_ap_sme_features {
  * @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested
  *     to work properly to suppport receiving regulatory hints from
  *     cellular base stations.
+ * @NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: (no longer available, only
+ *     here to reserve the value for API/ABI compatibility)
  * @NL80211_FEATURE_SAE: This driver supports simultaneous authentication of
  *     equals (SAE) with user space SME (NL80211_CMD_AUTHENTICATE) in station
  *     mode
@@ -3897,7 +3899,7 @@ enum nl80211_feature_flags {
        NL80211_FEATURE_HT_IBSS                         = 1 << 1,
        NL80211_FEATURE_INACTIVITY_TIMER                = 1 << 2,
        NL80211_FEATURE_CELL_BASE_REG_HINTS             = 1 << 3,
-       /* bit 4 is reserved - don't use */
+       NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL        = 1 << 4,
        NL80211_FEATURE_SAE                             = 1 << 5,
        NL80211_FEATURE_LOW_PRIORITY_SCAN               = 1 << 6,
        NL80211_FEATURE_SCAN_FLUSH                      = 1 << 7,
index 0cd5ca333fac1cdbaf40f5455cc566f798457d4e..de082130ba4b3913b51ff1ddfdf9bbfef153ad6b 100644 (file)
@@ -275,9 +275,9 @@ DEFINE_GUEST_HANDLE_STRUCT(mmu_update);
  * NB. The fields are natural register size for this architecture.
  */
 struct multicall_entry {
-    unsigned long op;
-    long result;
-    unsigned long args[6];
+    xen_ulong_t op;
+    xen_long_t result;
+    xen_ulong_t args[6];
 };
 DEFINE_GUEST_HANDLE_STRUCT(multicall_entry);
 
index 2cf47175b12b3504dc6ffa4f19d94b275358a194..0b3149ed7eaaa388d9054d371b5301a589d157ac 100644 (file)
@@ -9,10 +9,6 @@ DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
 
 void xen_arch_pre_suspend(void);
 void xen_arch_post_suspend(int suspend_cancelled);
-void xen_arch_hvm_post_suspend(int suspend_cancelled);
-
-void xen_mm_pin_all(void);
-void xen_mm_unpin_all(void);
 
 void xen_timer_resume(void);
 void xen_arch_resume(void);
index 9c7fd4c9249f2c72395fcaf2ac953f782a3e2b59..48655ceb66f45cdf27cf8bf769d9de296175a21c 100644 (file)
@@ -476,7 +476,7 @@ static void __init mm_init(void)
        vmalloc_init();
 }
 
-asmlinkage void __init start_kernel(void)
+asmlinkage __visible void __init start_kernel(void)
 {
        char * command_line;
        extern const struct kernel_param __start___param[], __stop___param[];
index 7c2893602d0651f767e1a177dbfd6214e66e8d9c..47845c57eb1925f5a24132dbc36bd95b256f7654 100644 (file)
@@ -643,13 +643,13 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
                if ((task_active_pid_ns(current) != &init_pid_ns))
                        return -EPERM;
 
-               if (!capable(CAP_AUDIT_CONTROL))
+               if (!netlink_capable(skb, CAP_AUDIT_CONTROL))
                        err = -EPERM;
                break;
        case AUDIT_USER:
        case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:
        case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2:
-               if (!capable(CAP_AUDIT_WRITE))
+               if (!netlink_capable(skb, CAP_AUDIT_WRITE))
                        err = -EPERM;
                break;
        default:  /* bad msg */
index 9fcdaa705b6cb7442b4babcb3a9ab40564afa27b..3f1ca934a2378495e5129dbe807bfc7111f53e8b 100644 (file)
@@ -348,7 +348,7 @@ struct cgrp_cset_link {
  * reference-counted, to improve performance when child cgroups
  * haven't been created.
  */
-static struct css_set init_css_set = {
+struct css_set init_css_set = {
        .refcount               = ATOMIC_INIT(1),
        .cgrp_links             = LIST_HEAD_INIT(init_css_set.cgrp_links),
        .tasks                  = LIST_HEAD_INIT(init_css_set.tasks),
@@ -1495,7 +1495,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
         */
        if (!use_task_css_set_links)
                cgroup_enable_task_cg_lists();
-retry:
+
        mutex_lock(&cgroup_tree_mutex);
        mutex_lock(&cgroup_mutex);
 
@@ -1503,7 +1503,7 @@ retry:
        ret = parse_cgroupfs_options(data, &opts);
        if (ret)
                goto out_unlock;
-
+retry:
        /* look for a matching existing root */
        if (!opts.subsys_mask && !opts.none && !opts.name) {
                cgrp_dfl_root_visible = true;
@@ -1562,9 +1562,9 @@ retry:
                if (!atomic_inc_not_zero(&root->cgrp.refcnt)) {
                        mutex_unlock(&cgroup_mutex);
                        mutex_unlock(&cgroup_tree_mutex);
-                       kfree(opts.release_agent);
-                       kfree(opts.name);
                        msleep(10);
+                       mutex_lock(&cgroup_tree_mutex);
+                       mutex_lock(&cgroup_mutex);
                        goto retry;
                }
 
index 2bc4a2256444ebf500269c5dc276871e48e0efa8..345628c78b5b3779460038ec6f036f9e8b7c1a32 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/uaccess.h>
 #include <linux/freezer.h>
 #include <linux/seq_file.h>
+#include <linux/mutex.h>
 
 /*
  * A cgroup is freezing if any FREEZING flags are set.  FREEZING_SELF is
@@ -42,9 +43,10 @@ enum freezer_state_flags {
 struct freezer {
        struct cgroup_subsys_state      css;
        unsigned int                    state;
-       spinlock_t                      lock;
 };
 
+static DEFINE_MUTEX(freezer_mutex);
+
 static inline struct freezer *css_freezer(struct cgroup_subsys_state *css)
 {
        return css ? container_of(css, struct freezer, css) : NULL;
@@ -93,7 +95,6 @@ freezer_css_alloc(struct cgroup_subsys_state *parent_css)
        if (!freezer)
                return ERR_PTR(-ENOMEM);
 
-       spin_lock_init(&freezer->lock);
        return &freezer->css;
 }
 
@@ -110,14 +111,7 @@ static int freezer_css_online(struct cgroup_subsys_state *css)
        struct freezer *freezer = css_freezer(css);
        struct freezer *parent = parent_freezer(freezer);
 
-       /*
-        * The following double locking and freezing state inheritance
-        * guarantee that @cgroup can never escape ancestors' freezing
-        * states.  See css_for_each_descendant_pre() for details.
-        */
-       if (parent)
-               spin_lock_irq(&parent->lock);
-       spin_lock_nested(&freezer->lock, SINGLE_DEPTH_NESTING);
+       mutex_lock(&freezer_mutex);
 
        freezer->state |= CGROUP_FREEZER_ONLINE;
 
@@ -126,10 +120,7 @@ static int freezer_css_online(struct cgroup_subsys_state *css)
                atomic_inc(&system_freezing_cnt);
        }
 
-       spin_unlock(&freezer->lock);
-       if (parent)
-               spin_unlock_irq(&parent->lock);
-
+       mutex_unlock(&freezer_mutex);
        return 0;
 }
 
@@ -144,14 +135,14 @@ static void freezer_css_offline(struct cgroup_subsys_state *css)
 {
        struct freezer *freezer = css_freezer(css);
 
-       spin_lock_irq(&freezer->lock);
+       mutex_lock(&freezer_mutex);
 
        if (freezer->state & CGROUP_FREEZING)
                atomic_dec(&system_freezing_cnt);
 
        freezer->state = 0;
 
-       spin_unlock_irq(&freezer->lock);
+       mutex_unlock(&freezer_mutex);
 }
 
 static void freezer_css_free(struct cgroup_subsys_state *css)
@@ -175,7 +166,7 @@ static void freezer_attach(struct cgroup_subsys_state *new_css,
        struct task_struct *task;
        bool clear_frozen = false;
 
-       spin_lock_irq(&freezer->lock);
+       mutex_lock(&freezer_mutex);
 
        /*
         * Make the new tasks conform to the current state of @new_css.
@@ -197,21 +188,13 @@ static void freezer_attach(struct cgroup_subsys_state *new_css,
                }
        }
 
-       spin_unlock_irq(&freezer->lock);
-
-       /*
-        * Propagate FROZEN clearing upwards.  We may race with
-        * update_if_frozen(), but as long as both work bottom-up, either
-        * update_if_frozen() sees child's FROZEN cleared or we clear the
-        * parent's FROZEN later.  No parent w/ !FROZEN children can be
-        * left FROZEN.
-        */
+       /* propagate FROZEN clearing upwards */
        while (clear_frozen && (freezer = parent_freezer(freezer))) {
-               spin_lock_irq(&freezer->lock);
                freezer->state &= ~CGROUP_FROZEN;
                clear_frozen = freezer->state & CGROUP_FREEZING;
-               spin_unlock_irq(&freezer->lock);
        }
+
+       mutex_unlock(&freezer_mutex);
 }
 
 /**
@@ -228,9 +211,6 @@ static void freezer_fork(struct task_struct *task)
 {
        struct freezer *freezer;
 
-       rcu_read_lock();
-       freezer = task_freezer(task);
-
        /*
         * The root cgroup is non-freezable, so we can skip locking the
         * freezer.  This is safe regardless of race with task migration.
@@ -238,24 +218,18 @@ static void freezer_fork(struct task_struct *task)
         * to do.  If we lost and root is the new cgroup, noop is still the
         * right thing to do.
         */
-       if (!parent_freezer(freezer))
-               goto out;
+       if (task_css_is_root(task, freezer_cgrp_id))
+               return;
 
-       /*
-        * Grab @freezer->lock and freeze @task after verifying @task still
-        * belongs to @freezer and it's freezing.  The former is for the
-        * case where we have raced against task migration and lost and
-        * @task is already in a different cgroup which may not be frozen.
-        * This isn't strictly necessary as freeze_task() is allowed to be
-        * called spuriously but let's do it anyway for, if nothing else,
-        * documentation.
-        */
-       spin_lock_irq(&freezer->lock);
-       if (freezer == task_freezer(task) && (freezer->state & CGROUP_FREEZING))
+       mutex_lock(&freezer_mutex);
+       rcu_read_lock();
+
+       freezer = task_freezer(task);
+       if (freezer->state & CGROUP_FREEZING)
                freeze_task(task);
-       spin_unlock_irq(&freezer->lock);
-out:
+
        rcu_read_unlock();
+       mutex_unlock(&freezer_mutex);
 }
 
 /**
@@ -281,22 +255,24 @@ static void update_if_frozen(struct cgroup_subsys_state *css)
        struct css_task_iter it;
        struct task_struct *task;
 
-       WARN_ON_ONCE(!rcu_read_lock_held());
-
-       spin_lock_irq(&freezer->lock);
+       lockdep_assert_held(&freezer_mutex);
 
        if (!(freezer->state & CGROUP_FREEZING) ||
            (freezer->state & CGROUP_FROZEN))
-               goto out_unlock;
+               return;
 
        /* are all (live) children frozen? */
+       rcu_read_lock();
        css_for_each_child(pos, css) {
                struct freezer *child = css_freezer(pos);
 
                if ((child->state & CGROUP_FREEZER_ONLINE) &&
-                   !(child->state & CGROUP_FROZEN))
-                       goto out_unlock;
+                   !(child->state & CGROUP_FROZEN)) {
+                       rcu_read_unlock();
+                       return;
+               }
        }
+       rcu_read_unlock();
 
        /* are all tasks frozen? */
        css_task_iter_start(css, &it);
@@ -317,21 +293,29 @@ static void update_if_frozen(struct cgroup_subsys_state *css)
        freezer->state |= CGROUP_FROZEN;
 out_iter_end:
        css_task_iter_end(&it);
-out_unlock:
-       spin_unlock_irq(&freezer->lock);
 }
 
 static int freezer_read(struct seq_file *m, void *v)
 {
        struct cgroup_subsys_state *css = seq_css(m), *pos;
 
+       mutex_lock(&freezer_mutex);
        rcu_read_lock();
 
        /* update states bottom-up */
-       css_for_each_descendant_post(pos, css)
+       css_for_each_descendant_post(pos, css) {
+               if (!css_tryget(pos))
+                       continue;
+               rcu_read_unlock();
+
                update_if_frozen(pos);
 
+               rcu_read_lock();
+               css_put(pos);
+       }
+
        rcu_read_unlock();
+       mutex_unlock(&freezer_mutex);
 
        seq_puts(m, freezer_state_strs(css_freezer(css)->state));
        seq_putc(m, '\n');
@@ -373,7 +357,7 @@ static void freezer_apply_state(struct freezer *freezer, bool freeze,
                                unsigned int state)
 {
        /* also synchronizes against task migration, see freezer_attach() */
-       lockdep_assert_held(&freezer->lock);
+       lockdep_assert_held(&freezer_mutex);
 
        if (!(freezer->state & CGROUP_FREEZER_ONLINE))
                return;
@@ -414,31 +398,29 @@ static void freezer_change_state(struct freezer *freezer, bool freeze)
         * descendant will try to inherit its parent's FREEZING state as
         * CGROUP_FREEZING_PARENT.
         */
+       mutex_lock(&freezer_mutex);
        rcu_read_lock();
        css_for_each_descendant_pre(pos, &freezer->css) {
                struct freezer *pos_f = css_freezer(pos);
                struct freezer *parent = parent_freezer(pos_f);
 
-               spin_lock_irq(&pos_f->lock);
+               if (!css_tryget(pos))
+                       continue;
+               rcu_read_unlock();
 
-               if (pos_f == freezer) {
+               if (pos_f == freezer)
                        freezer_apply_state(pos_f, freeze,
                                            CGROUP_FREEZING_SELF);
-               } else {
-                       /*
-                        * Our update to @parent->state is already visible
-                        * which is all we need.  No need to lock @parent.
-                        * For more info on synchronization, see
-                        * freezer_post_create().
-                        */
+               else
                        freezer_apply_state(pos_f,
                                            parent->state & CGROUP_FREEZING,
                                            CGROUP_FREEZING_PARENT);
-               }
 
-               spin_unlock_irq(&pos_f->lock);
+               rcu_read_lock();
+               css_put(pos);
        }
        rcu_read_unlock();
+       mutex_unlock(&freezer_mutex);
 }
 
 static int freezer_write(struct cgroup_subsys_state *css, struct cftype *cft,
index 6cb20d2e7ee0d28b0d6399a8cd1f3e23f9366899..019d45008448cc54160fd25edd5bbde1cc279e50 100644 (file)
@@ -120,7 +120,7 @@ void context_tracking_user_enter(void)
  * instead of preempt_schedule() to exit user context if needed before
  * calling the scheduler.
  */
-asmlinkage void __sched notrace preempt_schedule_context(void)
+asmlinkage __visible void __sched notrace preempt_schedule_context(void)
 {
        enum ctx_state prev_ctx;
 
index a9e710eef0e2543f063ee8a1c06952f2fb3e0891..247979a1b815660b61100e5c9168ea85c690a4c7 100644 (file)
@@ -726,10 +726,12 @@ void set_cpu_present(unsigned int cpu, bool present)
 
 void set_cpu_online(unsigned int cpu, bool online)
 {
-       if (online)
+       if (online) {
                cpumask_set_cpu(cpu, to_cpumask(cpu_online_bits));
-       else
+               cpumask_set_cpu(cpu, to_cpumask(cpu_active_bits));
+       } else {
                cpumask_clear_cpu(cpu, to_cpumask(cpu_online_bits));
+       }
 }
 
 void set_cpu_active(unsigned int cpu, bool active)
index f83a71a3e46d75547e540ed317f99531838f408b..440eefc67397e48f15b58bc8cf31712bec91286b 100644 (file)
@@ -1443,6 +1443,11 @@ group_sched_out(struct perf_event *group_event,
                cpuctx->exclusive = 0;
 }
 
+struct remove_event {
+       struct perf_event *event;
+       bool detach_group;
+};
+
 /*
  * Cross CPU call to remove a performance event
  *
@@ -1451,12 +1456,15 @@ group_sched_out(struct perf_event *group_event,
  */
 static int __perf_remove_from_context(void *info)
 {
-       struct perf_event *event = info;
+       struct remove_event *re = info;
+       struct perf_event *event = re->event;
        struct perf_event_context *ctx = event->ctx;
        struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
 
        raw_spin_lock(&ctx->lock);
        event_sched_out(event, cpuctx, ctx);
+       if (re->detach_group)
+               perf_group_detach(event);
        list_del_event(event, ctx);
        if (!ctx->nr_events && cpuctx->task_ctx == ctx) {
                ctx->is_active = 0;
@@ -1481,10 +1489,14 @@ static int __perf_remove_from_context(void *info)
  * When called from perf_event_exit_task, it's OK because the
  * context has been detached from its task.
  */
-static void perf_remove_from_context(struct perf_event *event)
+static void perf_remove_from_context(struct perf_event *event, bool detach_group)
 {
        struct perf_event_context *ctx = event->ctx;
        struct task_struct *task = ctx->task;
+       struct remove_event re = {
+               .event = event,
+               .detach_group = detach_group,
+       };
 
        lockdep_assert_held(&ctx->mutex);
 
@@ -1493,12 +1505,12 @@ static void perf_remove_from_context(struct perf_event *event)
                 * Per cpu events are removed via an smp call and
                 * the removal is always successful.
                 */
-               cpu_function_call(event->cpu, __perf_remove_from_context, event);
+               cpu_function_call(event->cpu, __perf_remove_from_context, &re);
                return;
        }
 
 retry:
-       if (!task_function_call(task, __perf_remove_from_context, event))
+       if (!task_function_call(task, __perf_remove_from_context, &re))
                return;
 
        raw_spin_lock_irq(&ctx->lock);
@@ -1515,6 +1527,8 @@ retry:
         * Since the task isn't running, its safe to remove the event, us
         * holding the ctx->lock ensures the task won't get scheduled in.
         */
+       if (detach_group)
+               perf_group_detach(event);
        list_del_event(event, ctx);
        raw_spin_unlock_irq(&ctx->lock);
 }
@@ -3178,7 +3192,8 @@ static void free_event_rcu(struct rcu_head *head)
 }
 
 static void ring_buffer_put(struct ring_buffer *rb);
-static void ring_buffer_detach(struct perf_event *event, struct ring_buffer *rb);
+static void ring_buffer_attach(struct perf_event *event,
+                              struct ring_buffer *rb);
 
 static void unaccount_event_cpu(struct perf_event *event, int cpu)
 {
@@ -3238,8 +3253,6 @@ static void free_event(struct perf_event *event)
        unaccount_event(event);
 
        if (event->rb) {
-               struct ring_buffer *rb;
-
                /*
                 * Can happen when we close an event with re-directed output.
                 *
@@ -3247,12 +3260,7 @@ static void free_event(struct perf_event *event)
                 * over us; possibly making our ring_buffer_put() the last.
                 */
                mutex_lock(&event->mmap_mutex);
-               rb = event->rb;
-               if (rb) {
-                       rcu_assign_pointer(event->rb, NULL);
-                       ring_buffer_detach(event, rb);
-                       ring_buffer_put(rb); /* could be last */
-               }
+               ring_buffer_attach(event, NULL);
                mutex_unlock(&event->mmap_mutex);
        }
 
@@ -3281,10 +3289,7 @@ int perf_event_release_kernel(struct perf_event *event)
         *     to trigger the AB-BA case.
         */
        mutex_lock_nested(&ctx->mutex, SINGLE_DEPTH_NESTING);
-       raw_spin_lock_irq(&ctx->lock);
-       perf_group_detach(event);
-       raw_spin_unlock_irq(&ctx->lock);
-       perf_remove_from_context(event);
+       perf_remove_from_context(event, true);
        mutex_unlock(&ctx->mutex);
 
        free_event(event);
@@ -3839,28 +3844,47 @@ unlock:
 static void ring_buffer_attach(struct perf_event *event,
                               struct ring_buffer *rb)
 {
+       struct ring_buffer *old_rb = NULL;
        unsigned long flags;
 
-       if (!list_empty(&event->rb_entry))
-               return;
+       if (event->rb) {
+               /*
+                * Should be impossible, we set this when removing
+                * event->rb_entry and wait/clear when adding event->rb_entry.
+                */
+               WARN_ON_ONCE(event->rcu_pending);
 
-       spin_lock_irqsave(&rb->event_lock, flags);
-       if (list_empty(&event->rb_entry))
-               list_add(&event->rb_entry, &rb->event_list);
-       spin_unlock_irqrestore(&rb->event_lock, flags);
-}
+               old_rb = event->rb;
+               event->rcu_batches = get_state_synchronize_rcu();
+               event->rcu_pending = 1;
 
-static void ring_buffer_detach(struct perf_event *event, struct ring_buffer *rb)
-{
-       unsigned long flags;
+               spin_lock_irqsave(&old_rb->event_lock, flags);
+               list_del_rcu(&event->rb_entry);
+               spin_unlock_irqrestore(&old_rb->event_lock, flags);
+       }
 
-       if (list_empty(&event->rb_entry))
-               return;
+       if (event->rcu_pending && rb) {
+               cond_synchronize_rcu(event->rcu_batches);
+               event->rcu_pending = 0;
+       }
+
+       if (rb) {
+               spin_lock_irqsave(&rb->event_lock, flags);
+               list_add_rcu(&event->rb_entry, &rb->event_list);
+               spin_unlock_irqrestore(&rb->event_lock, flags);
+       }
+
+       rcu_assign_pointer(event->rb, rb);
 
-       spin_lock_irqsave(&rb->event_lock, flags);
-       list_del_init(&event->rb_entry);
-       wake_up_all(&event->waitq);
-       spin_unlock_irqrestore(&rb->event_lock, flags);
+       if (old_rb) {
+               ring_buffer_put(old_rb);
+               /*
+                * Since we detached before setting the new rb, so that we
+                * could attach the new rb, we could have missed a wakeup.
+                * Provide it now.
+                */
+               wake_up_all(&event->waitq);
+       }
 }
 
 static void ring_buffer_wakeup(struct perf_event *event)
@@ -3929,7 +3953,7 @@ static void perf_mmap_close(struct vm_area_struct *vma)
 {
        struct perf_event *event = vma->vm_file->private_data;
 
-       struct ring_buffer *rb = event->rb;
+       struct ring_buffer *rb = ring_buffer_get(event);
        struct user_struct *mmap_user = rb->mmap_user;
        int mmap_locked = rb->mmap_locked;
        unsigned long size = perf_data_size(rb);
@@ -3937,18 +3961,14 @@ static void perf_mmap_close(struct vm_area_struct *vma)
        atomic_dec(&rb->mmap_count);
 
        if (!atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex))
-               return;
+               goto out_put;
 
-       /* Detach current event from the buffer. */
-       rcu_assign_pointer(event->rb, NULL);
-       ring_buffer_detach(event, rb);
+       ring_buffer_attach(event, NULL);
        mutex_unlock(&event->mmap_mutex);
 
        /* If there's still other mmap()s of this buffer, we're done. */
-       if (atomic_read(&rb->mmap_count)) {
-               ring_buffer_put(rb); /* can't be last */
-               return;
-       }
+       if (atomic_read(&rb->mmap_count))
+               goto out_put;
 
        /*
         * No other mmap()s, detach from all other events that might redirect
@@ -3978,11 +3998,9 @@ again:
                 * still restart the iteration to make sure we're not now
                 * iterating the wrong list.
                 */
-               if (event->rb == rb) {
-                       rcu_assign_pointer(event->rb, NULL);
-                       ring_buffer_detach(event, rb);
-                       ring_buffer_put(rb); /* can't be last, we still have one */
-               }
+               if (event->rb == rb)
+                       ring_buffer_attach(event, NULL);
+
                mutex_unlock(&event->mmap_mutex);
                put_event(event);
 
@@ -4007,6 +4025,7 @@ again:
        vma->vm_mm->pinned_vm -= mmap_locked;
        free_uid(mmap_user);
 
+out_put:
        ring_buffer_put(rb); /* could be last */
 }
 
@@ -4124,7 +4143,6 @@ again:
        vma->vm_mm->pinned_vm += extra;
 
        ring_buffer_attach(event, rb);
-       rcu_assign_pointer(event->rb, rb);
 
        perf_event_init_userpage(event);
        perf_event_update_userpage(event);
@@ -5408,6 +5426,9 @@ struct swevent_htable {
 
        /* Recursion avoidance in each contexts */
        int                             recursion[PERF_NR_CONTEXTS];
+
+       /* Keeps track of cpu being initialized/exited */
+       bool                            online;
 };
 
 static DEFINE_PER_CPU(struct swevent_htable, swevent_htable);
@@ -5654,8 +5675,14 @@ static int perf_swevent_add(struct perf_event *event, int flags)
        hwc->state = !(flags & PERF_EF_START);
 
        head = find_swevent_head(swhash, event);
-       if (WARN_ON_ONCE(!head))
+       if (!head) {
+               /*
+                * We can race with cpu hotplug code. Do not
+                * WARN if the cpu just got unplugged.
+                */
+               WARN_ON_ONCE(swhash->online);
                return -EINVAL;
+       }
 
        hlist_add_head_rcu(&event->hlist_entry, head);
 
@@ -6914,7 +6941,7 @@ err_size:
 static int
 perf_event_set_output(struct perf_event *event, struct perf_event *output_event)
 {
-       struct ring_buffer *rb = NULL, *old_rb = NULL;
+       struct ring_buffer *rb = NULL;
        int ret = -EINVAL;
 
        if (!output_event)
@@ -6942,8 +6969,6 @@ set:
        if (atomic_read(&event->mmap_count))
                goto unlock;
 
-       old_rb = event->rb;
-
        if (output_event) {
                /* get the rb we want to redirect to */
                rb = ring_buffer_get(output_event);
@@ -6951,23 +6976,7 @@ set:
                        goto unlock;
        }
 
-       if (old_rb)
-               ring_buffer_detach(event, old_rb);
-
-       if (rb)
-               ring_buffer_attach(event, rb);
-
-       rcu_assign_pointer(event->rb, rb);
-
-       if (old_rb) {
-               ring_buffer_put(old_rb);
-               /*
-                * Since we detached before setting the new rb, so that we
-                * could attach the new rb, we could have missed a wakeup.
-                * Provide it now.
-                */
-               wake_up_all(&event->waitq);
-       }
+       ring_buffer_attach(event, rb);
 
        ret = 0;
 unlock:
@@ -7018,6 +7027,9 @@ SYSCALL_DEFINE5(perf_event_open,
        if (attr.freq) {
                if (attr.sample_freq > sysctl_perf_event_sample_rate)
                        return -EINVAL;
+       } else {
+               if (attr.sample_period & (1ULL << 63))
+                       return -EINVAL;
        }
 
        /*
@@ -7165,7 +7177,7 @@ SYSCALL_DEFINE5(perf_event_open,
                struct perf_event_context *gctx = group_leader->ctx;
 
                mutex_lock(&gctx->mutex);
-               perf_remove_from_context(group_leader);
+               perf_remove_from_context(group_leader, false);
 
                /*
                 * Removing from the context ends up with disabled
@@ -7175,7 +7187,7 @@ SYSCALL_DEFINE5(perf_event_open,
                perf_event__state_init(group_leader);
                list_for_each_entry(sibling, &group_leader->sibling_list,
                                    group_entry) {
-                       perf_remove_from_context(sibling);
+                       perf_remove_from_context(sibling, false);
                        perf_event__state_init(sibling);
                        put_ctx(gctx);
                }
@@ -7305,7 +7317,7 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu)
        mutex_lock(&src_ctx->mutex);
        list_for_each_entry_safe(event, tmp, &src_ctx->event_list,
                                 event_entry) {
-               perf_remove_from_context(event);
+               perf_remove_from_context(event, false);
                unaccount_event_cpu(event, src_cpu);
                put_ctx(src_ctx);
                list_add(&event->migrate_entry, &events);
@@ -7367,13 +7379,7 @@ __perf_event_exit_task(struct perf_event *child_event,
                         struct perf_event_context *child_ctx,
                         struct task_struct *child)
 {
-       if (child_event->parent) {
-               raw_spin_lock_irq(&child_ctx->lock);
-               perf_group_detach(child_event);
-               raw_spin_unlock_irq(&child_ctx->lock);
-       }
-
-       perf_remove_from_context(child_event);
+       perf_remove_from_context(child_event, !!child_event->parent);
 
        /*
         * It can happen that the parent exits first, and has events
@@ -7724,6 +7730,8 @@ int perf_event_init_context(struct task_struct *child, int ctxn)
         * swapped under us.
         */
        parent_ctx = perf_pin_task_context(parent, ctxn);
+       if (!parent_ctx)
+               return 0;
 
        /*
         * No need to check if parent_ctx != NULL here; since we saw
@@ -7835,6 +7843,7 @@ static void perf_event_init_cpu(int cpu)
        struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
 
        mutex_lock(&swhash->hlist_mutex);
+       swhash->online = true;
        if (swhash->hlist_refcount > 0) {
                struct swevent_hlist *hlist;
 
@@ -7857,14 +7866,14 @@ static void perf_pmu_rotate_stop(struct pmu *pmu)
 
 static void __perf_event_exit_context(void *__info)
 {
+       struct remove_event re = { .detach_group = false };
        struct perf_event_context *ctx = __info;
-       struct perf_event *event;
 
        perf_pmu_rotate_stop(ctx->pmu);
 
        rcu_read_lock();
-       list_for_each_entry_rcu(event, &ctx->event_list, event_entry)
-               __perf_remove_from_context(event);
+       list_for_each_entry_rcu(re.event, &ctx->event_list, event_entry)
+               __perf_remove_from_context(&re);
        rcu_read_unlock();
 }
 
@@ -7892,6 +7901,7 @@ static void perf_event_exit_cpu(int cpu)
        perf_event_exit_cpu_context(cpu);
 
        mutex_lock(&swhash->hlist_mutex);
+       swhash->online = false;
        swevent_hlist_release(swhash);
        mutex_unlock(&swhash->hlist_mutex);
 }
index 5f589279e4626c47b75b8a1d193d089f24a2f7b9..81dbe773ce4c20bdeafa8effa858cf85b995dfbe 100644 (file)
@@ -745,7 +745,8 @@ void exit_pi_state_list(struct task_struct *curr)
 
 static int
 lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
-               union futex_key *key, struct futex_pi_state **ps)
+               union futex_key *key, struct futex_pi_state **ps,
+               struct task_struct *task)
 {
        struct futex_pi_state *pi_state = NULL;
        struct futex_q *this, *next;
@@ -786,6 +787,16 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
                                        return -EINVAL;
                        }
 
+                       /*
+                        * Protect against a corrupted uval. If uval
+                        * is 0x80000000 then pid is 0 and the waiter
+                        * bit is set. So the deadlock check in the
+                        * calling code has failed and we did not fall
+                        * into the check above due to !pid.
+                        */
+                       if (task && pi_state->owner == task)
+                               return -EDEADLK;
+
                        atomic_inc(&pi_state->refcount);
                        *ps = pi_state;
 
@@ -803,6 +814,11 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
        if (!p)
                return -ESRCH;
 
+       if (!p->mm) {
+               put_task_struct(p);
+               return -EPERM;
+       }
+
        /*
         * We need to look at the task state flags to figure out,
         * whether the task is exiting. To protect against the do_exit
@@ -935,7 +951,7 @@ retry:
         * We dont have the lock. Look up the PI state (or create it if
         * we are the first waiter):
         */
-       ret = lookup_pi_state(uval, hb, key, ps);
+       ret = lookup_pi_state(uval, hb, key, ps, task);
 
        if (unlikely(ret)) {
                switch (ret) {
@@ -1347,7 +1363,7 @@ void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key,
  *
  * Return:
  *  0 - failed to acquire the lock atomically;
- *  1 - acquired the lock;
+ * >0 - acquired the lock, return value is vpid of the top_waiter
  * <0 - error
  */
 static int futex_proxy_trylock_atomic(u32 __user *pifutex,
@@ -1358,7 +1374,7 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex,
 {
        struct futex_q *top_waiter = NULL;
        u32 curval;
-       int ret;
+       int ret, vpid;
 
        if (get_futex_value_locked(&curval, pifutex))
                return -EFAULT;
@@ -1386,11 +1402,13 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex,
         * the contended case or if set_waiters is 1.  The pi_state is returned
         * in ps in contended cases.
         */
+       vpid = task_pid_vnr(top_waiter->task);
        ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task,
                                   set_waiters);
-       if (ret == 1)
+       if (ret == 1) {
                requeue_pi_wake_futex(top_waiter, key2, hb2);
-
+               return vpid;
+       }
        return ret;
 }
 
@@ -1421,7 +1439,6 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
        struct futex_pi_state *pi_state = NULL;
        struct futex_hash_bucket *hb1, *hb2;
        struct futex_q *this, *next;
-       u32 curval2;
 
        if (requeue_pi) {
                /*
@@ -1509,16 +1526,25 @@ retry_private:
                 * At this point the top_waiter has either taken uaddr2 or is
                 * waiting on it.  If the former, then the pi_state will not
                 * exist yet, look it up one more time to ensure we have a
-                * reference to it.
+                * reference to it. If the lock was taken, ret contains the
+                * vpid of the top waiter task.
                 */
-               if (ret == 1) {
+               if (ret > 0) {
                        WARN_ON(pi_state);
                        drop_count++;
                        task_count++;
-                       ret = get_futex_value_locked(&curval2, uaddr2);
-                       if (!ret)
-                               ret = lookup_pi_state(curval2, hb2, &key2,
-                                                     &pi_state);
+                       /*
+                        * If we acquired the lock, then the user
+                        * space value of uaddr2 should be vpid. It
+                        * cannot be changed by the top waiter as it
+                        * is blocked on hb2 lock if it tries to do
+                        * so. If something fiddled with it behind our
+                        * back the pi state lookup might unearth
+                        * it. So we rather use the known value than
+                        * rereading and handing potential crap to
+                        * lookup_pi_state.
+                        */
+                       ret = lookup_pi_state(ret, hb2, &key2, &pi_state, NULL);
                }
 
                switch (ret) {
index 6b715c0af1b117b5b61bd32629a00845f0313557..e0501fe7140d7c97daba3f3438b51272cf6d9932 100644 (file)
@@ -990,11 +990,8 @@ int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
        /* Remove an active timer from the queue: */
        ret = remove_hrtimer(timer, base);
 
-       /* Switch the timer base, if necessary: */
-       new_base = switch_hrtimer_base(timer, base, mode & HRTIMER_MODE_PINNED);
-
        if (mode & HRTIMER_MODE_REL) {
-               tim = ktime_add_safe(tim, new_base->get_time());
+               tim = ktime_add_safe(tim, base->get_time());
                /*
                 * CONFIG_TIME_LOW_RES is a temporary way for architectures
                 * to signal that they simply return xtime in
@@ -1009,6 +1006,9 @@ int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
 
        hrtimer_set_expires_range_ns(timer, tim, delta_ns);
 
+       /* Switch the timer base, if necessary: */
+       new_base = switch_hrtimer_base(timer, base, mode & HRTIMER_MODE_PINNED);
+
        timer_stats_hrtimer_set_start_info(timer);
 
        leftmost = enqueue_hrtimer(timer, new_base);
index c8380ad203bcd5fe8e78bf9570725730733791f0..28c57069ef681f726f2df133d36e6319d370c25f 100644 (file)
@@ -1683,6 +1683,14 @@ int kernel_kexec(void)
                kexec_in_progress = true;
                kernel_restart_prepare(NULL);
                migrate_to_reboot_cpu();
+
+               /*
+                * migrate_to_reboot_cpu() disables CPU hotplug assuming that
+                * no further code needs to use CPU hotplug (which is true in
+                * the reboot case). However, the kexec path depends on using
+                * CPU hotplug again; so re-enable it here.
+                */
+               cpu_hotplug_enable();
                printk(KERN_EMERG "Starting new kernel\n");
                machine_shutdown();
        }
index b0e9467922e1a476bfe1d4d8503ac7623affcaea..d24e4339b46d3c84d03f6998c44bc14035054aa6 100644 (file)
@@ -4188,7 +4188,7 @@ void debug_show_held_locks(struct task_struct *task)
 }
 EXPORT_SYMBOL_GPL(debug_show_held_locks);
 
-asmlinkage void lockdep_sys_exit(void)
+asmlinkage __visible void lockdep_sys_exit(void)
 {
        struct task_struct *curr = current;
 
index aa4dff04b594c2b058ba2193ef44644ff8dd54dc..a620d4d08ca6c17580f0bbb76d7c3ac9129330b9 100644 (file)
@@ -343,9 +343,16 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
         * top_waiter can be NULL, when we are in the deboosting
         * mode!
         */
-       if (top_waiter && (!task_has_pi_waiters(task) ||
-                          top_waiter != task_top_pi_waiter(task)))
-               goto out_unlock_pi;
+       if (top_waiter) {
+               if (!task_has_pi_waiters(task))
+                       goto out_unlock_pi;
+               /*
+                * If deadlock detection is off, we stop here if we
+                * are not the top pi waiter of the task.
+                */
+               if (!detect_deadlock && top_waiter != task_top_pi_waiter(task))
+                       goto out_unlock_pi;
+       }
 
        /*
         * When deadlock detection is off then we check, if further
@@ -361,7 +368,12 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
                goto retry;
        }
 
-       /* Deadlock detection */
+       /*
+        * Deadlock detection. If the lock is the same as the original
+        * lock which caused us to walk the lock chain or if the
+        * current lock is owned by the task which initiated the chain
+        * walk, we detected a deadlock.
+        */
        if (lock == orig_lock || rt_mutex_owner(lock) == top_task) {
                debug_rt_mutex_deadlock(deadlock_detect, orig_waiter, lock);
                raw_spin_unlock(&lock->wait_lock);
@@ -527,6 +539,18 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock,
        unsigned long flags;
        int chain_walk = 0, res;
 
+       /*
+        * Early deadlock detection. We really don't want the task to
+        * enqueue on itself just to untangle the mess later. It's not
+        * only an optimization. We drop the locks, so another waiter
+        * can come in before the chain walk detects the deadlock. So
+        * the other will detect the deadlock and return -EDEADLOCK,
+        * which is wrong, as the other waiter is not in a deadlock
+        * situation.
+        */
+       if (detect_deadlock && owner == task)
+               return -EDEADLK;
+
        raw_spin_lock_irqsave(&task->pi_lock, flags);
        __rt_mutex_adjust_prio(task);
        waiter->task = task;
index 18fb7a2fb14b315cf3f7f9a7bdaf0173438d57b5..1ea328aafdc9a7437d01e19b46033f7fd7fe5412 100644 (file)
@@ -1586,7 +1586,7 @@ swsusp_alloc(struct memory_bitmap *orig_bm, struct memory_bitmap *copy_bm,
        return -ENOMEM;
 }
 
-asmlinkage int swsusp_save(void)
+asmlinkage __visible int swsusp_save(void)
 {
        unsigned int nr_pages, nr_highmem;
 
index a45b509622952a751fda8f962c143f9ef684aedf..7228258b85eca19e105df60bf3101bbc8a5e30b4 100644 (file)
@@ -1674,7 +1674,7 @@ EXPORT_SYMBOL(printk_emit);
  *
  * See the vsnprintf() documentation for format string extensions over C99.
  */
-asmlinkage int printk(const char *fmt, ...)
+asmlinkage __visible int printk(const char *fmt, ...)
 {
        va_list args;
        int r;
@@ -1737,7 +1737,7 @@ void early_vprintk(const char *fmt, va_list ap)
        }
 }
 
-asmlinkage void early_printk(const char *fmt, ...)
+asmlinkage __visible void early_printk(const char *fmt, ...)
 {
        va_list ap;
 
index 268a45ea238cc84f51ae7612bf0ba3c531b9887f..0a725167898214344878217b48d4b97270ef3bd2 100644 (file)
@@ -2192,7 +2192,7 @@ static inline void post_schedule(struct rq *rq)
  * schedule_tail - first thing a freshly forked thread must call.
  * @prev: the thread we just switched away from.
  */
-asmlinkage void schedule_tail(struct task_struct *prev)
+asmlinkage __visible void schedule_tail(struct task_struct *prev)
        __releases(rq->lock)
 {
        struct rq *rq = this_rq();
@@ -2592,8 +2592,14 @@ pick_next_task(struct rq *rq, struct task_struct *prev)
        if (likely(prev->sched_class == class &&
                   rq->nr_running == rq->cfs.h_nr_running)) {
                p = fair_sched_class.pick_next_task(rq, prev);
-               if (likely(p && p != RETRY_TASK))
-                       return p;
+               if (unlikely(p == RETRY_TASK))
+                       goto again;
+
+               /* assumes fair_sched_class->next == idle_sched_class */
+               if (unlikely(!p))
+                       p = idle_sched_class.pick_next_task(rq, prev);
+
+               return p;
        }
 
 again:
@@ -2741,7 +2747,7 @@ static inline void sched_submit_work(struct task_struct *tsk)
                blk_schedule_flush_plug(tsk);
 }
 
-asmlinkage void __sched schedule(void)
+asmlinkage __visible void __sched schedule(void)
 {
        struct task_struct *tsk = current;
 
@@ -2751,7 +2757,7 @@ asmlinkage void __sched schedule(void)
 EXPORT_SYMBOL(schedule);
 
 #ifdef CONFIG_CONTEXT_TRACKING
-asmlinkage void __sched schedule_user(void)
+asmlinkage __visible void __sched schedule_user(void)
 {
        /*
         * If we come here after a random call to set_need_resched(),
@@ -2783,7 +2789,7 @@ void __sched schedule_preempt_disabled(void)
  * off of preempt_enable. Kernel preemptions off return from interrupt
  * occur there and call schedule directly.
  */
-asmlinkage void __sched notrace preempt_schedule(void)
+asmlinkage __visible void __sched notrace preempt_schedule(void)
 {
        /*
         * If there is a non-zero preempt_count or interrupts are disabled,
@@ -2813,7 +2819,7 @@ EXPORT_SYMBOL(preempt_schedule);
  * Note, that this is called and return with irqs disabled. This will
  * protect us against recursive calling from irq.
  */
-asmlinkage void __sched preempt_schedule_irq(void)
+asmlinkage __visible void __sched preempt_schedule_irq(void)
 {
        enum ctx_state prev_state;
 
@@ -3124,6 +3130,7 @@ __setparam_dl(struct task_struct *p, const struct sched_attr *attr)
        dl_se->dl_bw = to_ratio(dl_se->dl_period, dl_se->dl_runtime);
        dl_se->dl_throttled = 0;
        dl_se->dl_new = 1;
+       dl_se->dl_yielded = 0;
 }
 
 static void __setscheduler_params(struct task_struct *p,
@@ -3188,17 +3195,40 @@ __getparam_dl(struct task_struct *p, struct sched_attr *attr)
  * We ask for the deadline not being zero, and greater or equal
  * than the runtime, as well as the period of being zero or
  * greater than deadline. Furthermore, we have to be sure that
- * user parameters are above the internal resolution (1us); we
- * check sched_runtime only since it is always the smaller one.
+ * user parameters are above the internal resolution of 1us (we
+ * check sched_runtime only since it is always the smaller one) and
+ * below 2^63 ns (we have to check both sched_deadline and
+ * sched_period, as the latter can be zero).
  */
 static bool
 __checkparam_dl(const struct sched_attr *attr)
 {
-       return attr && attr->sched_deadline != 0 &&
-               (attr->sched_period == 0 ||
-               (s64)(attr->sched_period   - attr->sched_deadline) >= 0) &&
-               (s64)(attr->sched_deadline - attr->sched_runtime ) >= 0  &&
-               attr->sched_runtime >= (2 << (DL_SCALE - 1));
+       /* deadline != 0 */
+       if (attr->sched_deadline == 0)
+               return false;
+
+       /*
+        * Since we truncate DL_SCALE bits, make sure we're at least
+        * that big.
+        */
+       if (attr->sched_runtime < (1ULL << DL_SCALE))
+               return false;
+
+       /*
+        * Since we use the MSB for wrap-around and sign issues, make
+        * sure it's not set (mind that period can be equal to zero).
+        */
+       if (attr->sched_deadline & (1ULL << 63) ||
+           attr->sched_period & (1ULL << 63))
+               return false;
+
+       /* runtime <= deadline <= period (if period != 0) */
+       if ((attr->sched_period != 0 &&
+            attr->sched_period < attr->sched_deadline) ||
+           attr->sched_deadline < attr->sched_runtime)
+               return false;
+
+       return true;
 }
 
 /*
@@ -3639,6 +3669,7 @@ SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param)
  * sys_sched_setattr - same as above, but with extended sched_attr
  * @pid: the pid in question.
  * @uattr: structure containing the extended parameters.
+ * @flags: for future extension.
  */
 SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr,
                               unsigned int, flags)
@@ -3650,8 +3681,12 @@ SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr,
        if (!uattr || pid < 0 || flags)
                return -EINVAL;
 
-       if (sched_copy_attr(uattr, &attr))
-               return -EFAULT;
+       retval = sched_copy_attr(uattr, &attr);
+       if (retval)
+               return retval;
+
+       if (attr.sched_policy < 0)
+               return -EINVAL;
 
        rcu_read_lock();
        retval = -ESRCH;
@@ -3701,7 +3736,7 @@ SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid)
  */
 SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
 {
-       struct sched_param lp;
+       struct sched_param lp = { .sched_priority = 0 };
        struct task_struct *p;
        int retval;
 
@@ -3718,11 +3753,8 @@ SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
        if (retval)
                goto out_unlock;
 
-       if (task_has_dl_policy(p)) {
-               retval = -EINVAL;
-               goto out_unlock;
-       }
-       lp.sched_priority = p->rt_priority;
+       if (task_has_rt_policy(p))
+               lp.sched_priority = p->rt_priority;
        rcu_read_unlock();
 
        /*
@@ -3783,6 +3815,7 @@ err_size:
  * @pid: the pid in question.
  * @uattr: structure containing the extended parameters.
  * @size: sizeof(attr) for fwd/bwd comp.
+ * @flags: for future extension.
  */
 SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
                unsigned int, size, unsigned int, flags)
@@ -5043,7 +5076,6 @@ static int sched_cpu_active(struct notifier_block *nfb,
                                      unsigned long action, void *hcpu)
 {
        switch (action & ~CPU_TASKS_FROZEN) {
-       case CPU_STARTING:
        case CPU_DOWN_FAILED:
                set_cpu_active((long)hcpu, true);
                return NOTIFY_OK;
@@ -6017,6 +6049,8 @@ sd_numa_init(struct sched_domain_topology_level *tl, int cpu)
                                        ,
                .last_balance           = jiffies,
                .balance_interval       = sd_weight,
+               .max_newidle_lb_cost    = 0,
+               .next_decay_max_lb_cost = jiffies,
        };
        SD_INIT_NAME(sd, NUMA);
        sd->private = &tl->data;
index 5b9bb42b2d47e760f3a7cd17af24ba37d2cf07ea..bd95963dae80b92c34536d244de0986257e6490f 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/gfp.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include "cpudeadline.h"
 
 static inline int parent(int i)
@@ -39,8 +40,10 @@ static void cpudl_exchange(struct cpudl *cp, int a, int b)
 {
        int cpu_a = cp->elements[a].cpu, cpu_b = cp->elements[b].cpu;
 
-       swap(cp->elements[a], cp->elements[b]);
-       swap(cp->cpu_to_idx[cpu_a], cp->cpu_to_idx[cpu_b]);
+       swap(cp->elements[a].cpu, cp->elements[b].cpu);
+       swap(cp->elements[a].dl , cp->elements[b].dl );
+
+       swap(cp->elements[cpu_a].idx, cp->elements[cpu_b].idx);
 }
 
 static void cpudl_heapify(struct cpudl *cp, int idx)
@@ -140,7 +143,7 @@ void cpudl_set(struct cpudl *cp, int cpu, u64 dl, int is_valid)
        WARN_ON(!cpu_present(cpu));
 
        raw_spin_lock_irqsave(&cp->lock, flags);
-       old_idx = cp->cpu_to_idx[cpu];
+       old_idx = cp->elements[cpu].idx;
        if (!is_valid) {
                /* remove item */
                if (old_idx == IDX_INVALID) {
@@ -155,8 +158,8 @@ void cpudl_set(struct cpudl *cp, int cpu, u64 dl, int is_valid)
                cp->elements[old_idx].dl = cp->elements[cp->size - 1].dl;
                cp->elements[old_idx].cpu = new_cpu;
                cp->size--;
-               cp->cpu_to_idx[new_cpu] = old_idx;
-               cp->cpu_to_idx[cpu] = IDX_INVALID;
+               cp->elements[new_cpu].idx = old_idx;
+               cp->elements[cpu].idx = IDX_INVALID;
                while (old_idx > 0 && dl_time_before(
                                cp->elements[parent(old_idx)].dl,
                                cp->elements[old_idx].dl)) {
@@ -173,7 +176,7 @@ void cpudl_set(struct cpudl *cp, int cpu, u64 dl, int is_valid)
                cp->size++;
                cp->elements[cp->size - 1].dl = 0;
                cp->elements[cp->size - 1].cpu = cpu;
-               cp->cpu_to_idx[cpu] = cp->size - 1;
+               cp->elements[cpu].idx = cp->size - 1;
                cpudl_change_key(cp, cp->size - 1, dl);
                cpumask_clear_cpu(cpu, cp->free_cpus);
        } else {
@@ -195,10 +198,21 @@ int cpudl_init(struct cpudl *cp)
        memset(cp, 0, sizeof(*cp));
        raw_spin_lock_init(&cp->lock);
        cp->size = 0;
-       for (i = 0; i < NR_CPUS; i++)
-               cp->cpu_to_idx[i] = IDX_INVALID;
-       if (!alloc_cpumask_var(&cp->free_cpus, GFP_KERNEL))
+
+       cp->elements = kcalloc(nr_cpu_ids,
+                              sizeof(struct cpudl_item),
+                              GFP_KERNEL);
+       if (!cp->elements)
+               return -ENOMEM;
+
+       if (!alloc_cpumask_var(&cp->free_cpus, GFP_KERNEL)) {
+               kfree(cp->elements);
                return -ENOMEM;
+       }
+
+       for_each_possible_cpu(i)
+               cp->elements[i].idx = IDX_INVALID;
+
        cpumask_setall(cp->free_cpus);
 
        return 0;
@@ -210,7 +224,6 @@ int cpudl_init(struct cpudl *cp)
  */
 void cpudl_cleanup(struct cpudl *cp)
 {
-       /*
-        * nothing to do for the moment
-        */
+       free_cpumask_var(cp->free_cpus);
+       kfree(cp->elements);
 }
index a202789a412c2131e22ae64a935505f913e26a72..538c9796ad4a0b085e4c4284683fe7856b420153 100644 (file)
@@ -5,17 +5,17 @@
 
 #define IDX_INVALID     -1
 
-struct array_item {
+struct cpudl_item {
        u64 dl;
        int cpu;
+       int idx;
 };
 
 struct cpudl {
        raw_spinlock_t lock;
        int size;
-       int cpu_to_idx[NR_CPUS];
-       struct array_item elements[NR_CPUS];
        cpumask_var_t free_cpus;
+       struct cpudl_item *elements;
 };
 
 
index 8b836b376d9129760066326eabf5040f72b2e4f3..8834243abee2caa5451710cbe8230e3677ce7500 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/gfp.h>
 #include <linux/sched.h>
 #include <linux/sched/rt.h>
+#include <linux/slab.h>
 #include "cpupri.h"
 
 /* Convert between a 140 based task->prio, and our 102 based cpupri */
@@ -70,8 +71,7 @@ int cpupri_find(struct cpupri *cp, struct task_struct *p,
        int idx = 0;
        int task_pri = convert_prio(p->prio);
 
-       if (task_pri >= MAX_RT_PRIO)
-               return 0;
+       BUG_ON(task_pri >= CPUPRI_NR_PRIORITIES);
 
        for (idx = 0; idx < task_pri; idx++) {
                struct cpupri_vec *vec  = &cp->pri_to_cpu[idx];
@@ -219,8 +219,13 @@ int cpupri_init(struct cpupri *cp)
                        goto cleanup;
        }
 
+       cp->cpu_to_pri = kcalloc(nr_cpu_ids, sizeof(int), GFP_KERNEL);
+       if (!cp->cpu_to_pri)
+               goto cleanup;
+
        for_each_possible_cpu(i)
                cp->cpu_to_pri[i] = CPUPRI_INVALID;
+
        return 0;
 
 cleanup:
@@ -237,6 +242,7 @@ void cpupri_cleanup(struct cpupri *cp)
 {
        int i;
 
+       kfree(cp->cpu_to_pri);
        for (i = 0; i < CPUPRI_NR_PRIORITIES; i++)
                free_cpumask_var(cp->pri_to_cpu[i].mask);
 }
index f6d756173491c87e3defef7e16547cd24d75fbfa..6b033347fdfd1c787bae013ba02d390e256a44f3 100644 (file)
@@ -17,7 +17,7 @@ struct cpupri_vec {
 
 struct cpupri {
        struct cpupri_vec pri_to_cpu[CPUPRI_NR_PRIORITIES];
-       int               cpu_to_pri[NR_CPUS];
+       int *cpu_to_pri;
 };
 
 #ifdef CONFIG_SMP
index a95097cb4591b5bfa2466adb5600895e782fc661..72fdf06ef8652d5cb443b080f53ac117bd5517ba 100644 (file)
@@ -332,50 +332,50 @@ out:
  * softirq as those do not count in task exec_runtime any more.
  */
 static void irqtime_account_process_tick(struct task_struct *p, int user_tick,
-                                               struct rq *rq)
+                                        struct rq *rq, int ticks)
 {
-       cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy);
+       cputime_t scaled = cputime_to_scaled(cputime_one_jiffy);
+       u64 cputime = (__force u64) cputime_one_jiffy;
        u64 *cpustat = kcpustat_this_cpu->cpustat;
 
        if (steal_account_process_tick())
                return;
 
+       cputime *= ticks;
+       scaled *= ticks;
+
        if (irqtime_account_hi_update()) {
-               cpustat[CPUTIME_IRQ] += (__force u64) cputime_one_jiffy;
+               cpustat[CPUTIME_IRQ] += cputime;
        } else if (irqtime_account_si_update()) {
-               cpustat[CPUTIME_SOFTIRQ] += (__force u64) cputime_one_jiffy;
+               cpustat[CPUTIME_SOFTIRQ] += cputime;
        } else if (this_cpu_ksoftirqd() == p) {
                /*
                 * ksoftirqd time do not get accounted in cpu_softirq_time.
                 * So, we have to handle it separately here.
                 * Also, p->stime needs to be updated for ksoftirqd.
                 */
-               __account_system_time(p, cputime_one_jiffy, one_jiffy_scaled,
-                                       CPUTIME_SOFTIRQ);
+               __account_system_time(p, cputime, scaled, CPUTIME_SOFTIRQ);
        } else if (user_tick) {
-               account_user_time(p, cputime_one_jiffy, one_jiffy_scaled);
+               account_user_time(p, cputimescaled);
        } else if (p == rq->idle) {
-               account_idle_time(cputime_one_jiffy);
+               account_idle_time(cputime);
        } else if (p->flags & PF_VCPU) { /* System time or guest time */
-               account_guest_time(p, cputime_one_jiffy, one_jiffy_scaled);
+               account_guest_time(p, cputimescaled);
        } else {
-               __account_system_time(p, cputime_one_jiffy, one_jiffy_scaled,
-                                       CPUTIME_SYSTEM);
+               __account_system_time(p, cputime, scaled,       CPUTIME_SYSTEM);
        }
 }
 
 static void irqtime_account_idle_ticks(int ticks)
 {
-       int i;
        struct rq *rq = this_rq();
 
-       for (i = 0; i < ticks; i++)
-               irqtime_account_process_tick(current, 0, rq);
+       irqtime_account_process_tick(current, 0, rq, ticks);
 }
 #else /* CONFIG_IRQ_TIME_ACCOUNTING */
 static inline void irqtime_account_idle_ticks(int ticks) {}
 static inline void irqtime_account_process_tick(struct task_struct *p, int user_tick,
-                                               struct rq *rq) {}
+                                               struct rq *rq, int nr_ticks) {}
 #endif /* CONFIG_IRQ_TIME_ACCOUNTING */
 
 /*
@@ -464,7 +464,7 @@ void account_process_tick(struct task_struct *p, int user_tick)
                return;
 
        if (sched_clock_irqtime) {
-               irqtime_account_process_tick(p, user_tick, rq);
+               irqtime_account_process_tick(p, user_tick, rq, 1);
                return;
        }
 
index b08095786cb8fff0c96773eb5f6a582da503bcb8..800e99b99075141421d82f0bdc07e42f09baea9d 100644 (file)
@@ -528,6 +528,7 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer)
        sched_clock_tick();
        update_rq_clock(rq);
        dl_se->dl_throttled = 0;
+       dl_se->dl_yielded = 0;
        if (p->on_rq) {
                enqueue_task_dl(rq, p, ENQUEUE_REPLENISH);
                if (task_has_dl_policy(rq->curr))
@@ -893,10 +894,10 @@ static void yield_task_dl(struct rq *rq)
         * We make the task go to sleep until its current deadline by
         * forcing its runtime to zero. This way, update_curr_dl() stops
         * it and the bandwidth timer will wake it up and will give it
-        * new scheduling parameters (thanks to dl_new=1).
+        * new scheduling parameters (thanks to dl_yielded=1).
         */
        if (p->dl.runtime > 0) {
-               rq->curr->dl.dl_new = 1;
+               rq->curr->dl.dl_yielded = 1;
                p->dl.runtime = 0;
        }
        update_curr_dl(rq);
index 7570dd969c2838e9aab12ba9cb2c24cb87e21855..0fdb96de81a5b8a92c302961769cdefdb5cad915 100644 (file)
@@ -6653,6 +6653,7 @@ static int idle_balance(struct rq *this_rq)
        int this_cpu = this_rq->cpu;
 
        idle_enter_fair(this_rq);
+
        /*
         * We must set idle_stamp _before_ calling idle_balance(), such that we
         * measure the duration of idle_balance() as idle time.
@@ -6705,14 +6706,16 @@ static int idle_balance(struct rq *this_rq)
 
        raw_spin_lock(&this_rq->lock);
 
+       if (curr_cost > this_rq->max_idle_balance_cost)
+               this_rq->max_idle_balance_cost = curr_cost;
+
        /*
-        * While browsing the domains, we released the rq lock.
-        * A task could have be enqueued in the meantime
+        * While browsing the domains, we released the rq lock, a task could
+        * have been enqueued in the meantime. Since we're not going idle,
+        * pretend we pulled a task.
         */
-       if (this_rq->cfs.h_nr_running && !pulled_task) {
+       if (this_rq->cfs.h_nr_running && !pulled_task)
                pulled_task = 1;
-               goto out;
-       }
 
        if (pulled_task || time_after(jiffies, this_rq->next_balance)) {
                /*
@@ -6722,9 +6725,6 @@ static int idle_balance(struct rq *this_rq)
                this_rq->next_balance = next_balance;
        }
 
-       if (curr_cost > this_rq->max_idle_balance_cost)
-               this_rq->max_idle_balance_cost = curr_cost;
-
 out:
        /* Is there a task of a high priority class? */
        if (this_rq->nr_running != this_rq->cfs.h_nr_running &&
index 33e4648ae0e7cd908671ef1a8ab60bbb562c097c..92f24f5e8d5281aa03cf51e77d26297b91643769 100644 (file)
@@ -223,7 +223,7 @@ static inline bool lockdep_softirq_start(void) { return false; }
 static inline void lockdep_softirq_end(bool in_hardirq) { }
 #endif
 
-asmlinkage void __do_softirq(void)
+asmlinkage __visible void __do_softirq(void)
 {
        unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
        unsigned long old_flags = current->flags;
@@ -299,7 +299,7 @@ restart:
        tsk_restore_flags(current, old_flags, PF_MEMALLOC);
 }
 
-asmlinkage void do_softirq(void)
+asmlinkage __visible void do_softirq(void)
 {
        __u32 pending;
        unsigned long flags;
index ac5b23cf7212c6ebb0045bedce2f13ee8d0a19b3..6620e5837ce2e361e6014caca35632ae48ab67cb 100644 (file)
@@ -188,7 +188,6 @@ static int tracepoint_add_func(struct tracepoint *tp,
                WARN_ON_ONCE(1);
                return PTR_ERR(old);
        }
-       release_probes(old);
 
        /*
         * rcu_assign_pointer has a smp_wmb() which makes sure that the new
@@ -200,6 +199,7 @@ static int tracepoint_add_func(struct tracepoint *tp,
        rcu_assign_pointer(tp->funcs, tp_funcs);
        if (!static_key_enabled(&tp->key))
                static_key_slow_inc(&tp->key);
+       release_probes(old);
        return 0;
 }
 
@@ -221,7 +221,6 @@ static int tracepoint_remove_func(struct tracepoint *tp,
                WARN_ON_ONCE(1);
                return PTR_ERR(old);
        }
-       release_probes(old);
 
        if (!tp_funcs) {
                /* Removed last function */
@@ -232,6 +231,7 @@ static int tracepoint_remove_func(struct tracepoint *tp,
                        static_key_slow_dec(&tp->key);
        }
        rcu_assign_pointer(tp->funcs, tp_funcs);
+       release_probes(old);
        return 0;
 }
 
index 0ee63af30bd14a4ad7f4b8f846d19b100fd596b3..8edc87185427cb17fa02ed93498fcf6f8301cb7e 100644 (file)
@@ -1916,6 +1916,12 @@ static void send_mayday(struct work_struct *work)
 
        /* mayday mayday mayday */
        if (list_empty(&pwq->mayday_node)) {
+               /*
+                * If @pwq is for an unbound wq, its base ref may be put at
+                * any time due to an attribute change.  Pin @pwq until the
+                * rescuer is done with it.
+                */
+               get_pwq(pwq);
                list_add_tail(&pwq->mayday_node, &wq->maydays);
                wake_up_process(wq->rescuer->task);
        }
@@ -2398,6 +2404,7 @@ static int rescuer_thread(void *__rescuer)
        struct worker *rescuer = __rescuer;
        struct workqueue_struct *wq = rescuer->rescue_wq;
        struct list_head *scheduled = &rescuer->scheduled;
+       bool should_stop;
 
        set_user_nice(current, RESCUER_NICE_LEVEL);
 
@@ -2409,11 +2416,15 @@ static int rescuer_thread(void *__rescuer)
 repeat:
        set_current_state(TASK_INTERRUPTIBLE);
 
-       if (kthread_should_stop()) {
-               __set_current_state(TASK_RUNNING);
-               rescuer->task->flags &= ~PF_WQ_WORKER;
-               return 0;
-       }
+       /*
+        * By the time the rescuer is requested to stop, the workqueue
+        * shouldn't have any work pending, but @wq->maydays may still have
+        * pwq(s) queued.  This can happen by non-rescuer workers consuming
+        * all the work items before the rescuer got to them.  Go through
+        * @wq->maydays processing before acting on should_stop so that the
+        * list is always empty on exit.
+        */
+       should_stop = kthread_should_stop();
 
        /* see whether any pwq is asking for help */
        spin_lock_irq(&wq_mayday_lock);
@@ -2444,6 +2455,12 @@ repeat:
 
                process_scheduled_works(rescuer);
 
+               /*
+                * Put the reference grabbed by send_mayday().  @pool won't
+                * go away while we're holding its lock.
+                */
+               put_pwq(pwq);
+
                /*
                 * Leave this pool.  If keep_working() is %true, notify a
                 * regular worker; otherwise, we end up with 0 concurrency
@@ -2459,6 +2476,12 @@ repeat:
 
        spin_unlock_irq(&wq_mayday_lock);
 
+       if (should_stop) {
+               __set_current_state(TASK_RUNNING);
+               rescuer->task->flags &= ~PF_WQ_WORKER;
+               return 0;
+       }
+
        /* rescuers should never participate in concurrency management */
        WARN_ON_ONCE(!(rescuer->flags & WORKER_NOT_RUNNING));
        schedule();
@@ -4100,7 +4123,8 @@ static void wq_update_unbound_numa(struct workqueue_struct *wq, int cpu,
        if (!pwq) {
                pr_warning("workqueue: allocation failed while updating NUMA affinity of \"%s\"\n",
                           wq->name);
-               goto out_unlock;
+               mutex_lock(&wq->mutex);
+               goto use_dfl_pwq;
        }
 
        /*
index f23b63f0a1c391303e6a13e7fb6495a6354aa9c0..6745c6230db3403629048256968443f51b777655 100644 (file)
@@ -23,7 +23,7 @@ static void __dump_stack(void)
 #ifdef CONFIG_SMP
 static atomic_t dump_lock = ATOMIC_INIT(-1);
 
-asmlinkage void dump_stack(void)
+asmlinkage __visible void dump_stack(void)
 {
        int was_locked;
        int old;
@@ -55,7 +55,7 @@ retry:
        preempt_enable();
 }
 #else
-asmlinkage void dump_stack(void)
+asmlinkage __visible void dump_stack(void)
 {
        __dump_stack();
 }
index ebe5880c29d6cbe2306054f19bda87ffb3daa59a..1b5a95f0fa013ca428e877ae39d6f0148a49cd61 100644 (file)
@@ -581,3 +581,18 @@ config PGTABLE_MAPPING
 
 config GENERIC_EARLY_IOREMAP
        bool
+
+config MAX_STACK_SIZE_MB
+       int "Maximum user stack size for 32-bit processes (MB)"
+       default 80
+       range 8 256 if METAG
+       range 8 2048
+       depends on STACK_GROWSUP && (!64BIT || COMPAT)
+       help
+         This is the maximum stack size in Megabytes in the VM layout of 32-bit
+         user processes when the stack grows upwards (currently only on parisc
+         and metag arch). The stack will be located at the highest memory
+         address minus the given value, unless the RLIMIT_STACK hard limit is
+         changed to a smaller value in which case that is used.
+
+         A sane initial value is 80 MB.
index 37f976287068cef4ed185836059da2cc12cdceda..627dc2e4320fdf976895e9b96c2c54d91b2b2760 100644 (file)
@@ -671,16 +671,20 @@ static void isolate_freepages(struct zone *zone,
                                struct compact_control *cc)
 {
        struct page *page;
-       unsigned long high_pfn, low_pfn, pfn, z_end_pfn, end_pfn;
+       unsigned long high_pfn, low_pfn, pfn, z_end_pfn;
        int nr_freepages = cc->nr_freepages;
        struct list_head *freelist = &cc->freepages;
 
        /*
         * Initialise the free scanner. The starting point is where we last
-        * scanned from (or the end of the zone if starting). The low point
-        * is the end of the pageblock the migration scanner is using.
+        * successfully isolated from, zone-cached value, or the end of the
+        * zone when isolating for the first time. We need this aligned to
+        * the pageblock boundary, because we do pfn -= pageblock_nr_pages
+        * in the for loop.
+        * The low boundary is the end of the pageblock the migration scanner
+        * is using.
         */
-       pfn = cc->free_pfn;
+       pfn = cc->free_pfn & ~(pageblock_nr_pages-1);
        low_pfn = ALIGN(cc->migrate_pfn + 1, pageblock_nr_pages);
 
        /*
@@ -700,6 +704,7 @@ static void isolate_freepages(struct zone *zone,
        for (; pfn >= low_pfn && cc->nr_migratepages > nr_freepages;
                                        pfn -= pageblock_nr_pages) {
                unsigned long isolated;
+               unsigned long end_pfn;
 
                /*
                 * This can iterate a massively long zone without finding any
@@ -734,13 +739,10 @@ static void isolate_freepages(struct zone *zone,
                isolated = 0;
 
                /*
-                * As pfn may not start aligned, pfn+pageblock_nr_page
-                * may cross a MAX_ORDER_NR_PAGES boundary and miss
-                * a pfn_valid check. Ensure isolate_freepages_block()
-                * only scans within a pageblock
+                * Take care when isolating in last pageblock of a zone which
+                * ends in the middle of a pageblock.
                 */
-               end_pfn = ALIGN(pfn + 1, pageblock_nr_pages);
-               end_pfn = min(end_pfn, z_end_pfn);
+               end_pfn = min(pfn + pageblock_nr_pages, z_end_pfn);
                isolated = isolate_freepages_block(cc, pfn, end_pfn,
                                                   freelist, false);
                nr_freepages += isolated;
index 5020b280a771a4929bee7dbf0c5aee3fab1dea8b..088358c8006bb9c109da188c2b5ccf4a91614114 100644 (file)
@@ -257,9 +257,11 @@ static int filemap_check_errors(struct address_space *mapping)
 {
        int ret = 0;
        /* Check for outstanding write errors */
-       if (test_and_clear_bit(AS_ENOSPC, &mapping->flags))
+       if (test_bit(AS_ENOSPC, &mapping->flags) &&
+           test_and_clear_bit(AS_ENOSPC, &mapping->flags))
                ret = -ENOSPC;
-       if (test_and_clear_bit(AS_EIO, &mapping->flags))
+       if (test_bit(AS_EIO, &mapping->flags) &&
+           test_and_clear_bit(AS_EIO, &mapping->flags))
                ret = -EIO;
        return ret;
 }
@@ -906,8 +908,8 @@ EXPORT_SYMBOL(page_cache_prev_hole);
  * Looks up the page cache slot at @mapping & @offset.  If there is a
  * page cache page, it is returned with an increased refcount.
  *
- * If the slot holds a shadow entry of a previously evicted page, it
- * is returned.
+ * If the slot holds a shadow entry of a previously evicted page, or a
+ * swap entry from shmem/tmpfs, it is returned.
  *
  * Otherwise, %NULL is returned.
  */
@@ -928,9 +930,9 @@ repeat:
                        if (radix_tree_deref_retry(page))
                                goto repeat;
                        /*
-                        * Otherwise, shmem/tmpfs must be storing a swap entry
-                        * here as an exceptional entry: so return it without
-                        * attempting to raise page count.
+                        * A shadow entry of a recently evicted page,
+                        * or a swap entry from shmem/tmpfs.  Return
+                        * it without attempting to raise page count.
                         */
                        goto out;
                }
@@ -983,8 +985,8 @@ EXPORT_SYMBOL(find_get_page);
  * page cache page, it is returned locked and with an increased
  * refcount.
  *
- * If the slot holds a shadow entry of a previously evicted page, it
- * is returned.
+ * If the slot holds a shadow entry of a previously evicted page, or a
+ * swap entry from shmem/tmpfs, it is returned.
  *
  * Otherwise, %NULL is returned.
  *
@@ -1099,8 +1101,8 @@ EXPORT_SYMBOL(find_or_create_page);
  * with ascending indexes.  There may be holes in the indices due to
  * not-present pages.
  *
- * Any shadow entries of evicted pages are included in the returned
- * array.
+ * Any shadow entries of evicted pages, or swap entries from
+ * shmem/tmpfs, are included in the returned array.
  *
  * find_get_entries() returns the number of pages and shadow entries
  * which were found.
@@ -1128,9 +1130,9 @@ repeat:
                        if (radix_tree_deref_retry(page))
                                goto restart;
                        /*
-                        * Otherwise, we must be storing a swap entry
-                        * here as an exceptional entry: so return it
-                        * without attempting to raise page count.
+                        * A shadow entry of a recently evicted page,
+                        * or a swap entry from shmem/tmpfs.  Return
+                        * it without attempting to raise page count.
                         */
                        goto export;
                }
@@ -1198,9 +1200,9 @@ repeat:
                                goto restart;
                        }
                        /*
-                        * Otherwise, shmem/tmpfs must be storing a swap entry
-                        * here as an exceptional entry: so skip over it -
-                        * we only reach this from invalidate_mapping_pages().
+                        * A shadow entry of a recently evicted page,
+                        * or a swap entry from shmem/tmpfs.  Skip
+                        * over it.
                         */
                        continue;
                }
@@ -1265,9 +1267,9 @@ repeat:
                                goto restart;
                        }
                        /*
-                        * Otherwise, shmem/tmpfs must be storing a swap entry
-                        * here as an exceptional entry: so stop looking for
-                        * contiguous pages.
+                        * A shadow entry of a recently evicted page,
+                        * or a swap entry from shmem/tmpfs.  Stop
+                        * looking for contiguous pages.
                         */
                        break;
                }
@@ -1341,10 +1343,17 @@ repeat:
                                goto restart;
                        }
                        /*
-                        * This function is never used on a shmem/tmpfs
-                        * mapping, so a swap entry won't be found here.
+                        * A shadow entry of a recently evicted page.
+                        *
+                        * Those entries should never be tagged, but
+                        * this tree walk is lockless and the tags are
+                        * looked up in bulk, one radix tree node at a
+                        * time, so there is a sizable window for page
+                        * reclaim to evict a page we saw tagged.
+                        *
+                        * Skip over it.
                         */
-                       BUG();
+                       continue;
                }
 
                if (!page_cache_get_speculative(page))
index 246192929a2d5c4c4aa424e15c6a7b88e929e785..c82290b9c1fcdb1b1dfdffcad699d6eb83ee8a43 100644 (file)
@@ -1981,11 +1981,7 @@ static int __init hugetlb_init(void)
 {
        int i;
 
-       /* Some platform decide whether they support huge pages at boot
-        * time. On these, such as powerpc, HPAGE_SHIFT is set to 0 when
-        * there is no such support
-        */
-       if (HPAGE_SHIFT == 0)
+       if (!hugepages_supported())
                return 0;
 
        if (!size_to_hstate(default_hstate_size)) {
@@ -2112,6 +2108,9 @@ static int hugetlb_sysctl_handler_common(bool obey_mempolicy,
        unsigned long tmp;
        int ret;
 
+       if (!hugepages_supported())
+               return -ENOTSUPP;
+
        tmp = h->max_huge_pages;
 
        if (write && h->order >= MAX_ORDER)
@@ -2165,6 +2164,9 @@ int hugetlb_overcommit_handler(struct ctl_table *table, int write,
        unsigned long tmp;
        int ret;
 
+       if (!hugepages_supported())
+               return -ENOTSUPP;
+
        tmp = h->nr_overcommit_huge_pages;
 
        if (write && h->order >= MAX_ORDER)
@@ -2190,6 +2192,8 @@ out:
 void hugetlb_report_meminfo(struct seq_file *m)
 {
        struct hstate *h = &default_hstate;
+       if (!hugepages_supported())
+               return;
        seq_printf(m,
                        "HugePages_Total:   %5lu\n"
                        "HugePages_Free:    %5lu\n"
@@ -2206,6 +2210,8 @@ void hugetlb_report_meminfo(struct seq_file *m)
 int hugetlb_report_node_meminfo(int nid, char *buf)
 {
        struct hstate *h = &default_hstate;
+       if (!hugepages_supported())
+               return 0;
        return sprintf(buf,
                "Node %d HugePages_Total: %5u\n"
                "Node %d HugePages_Free:  %5u\n"
@@ -2220,6 +2226,9 @@ void hugetlb_show_meminfo(void)
        struct hstate *h;
        int nid;
 
+       if (!hugepages_supported())
+               return;
+
        for_each_node_state(nid, N_MEMORY)
                for_each_hstate(h)
                        pr_info("Node %d hugepages_total=%u hugepages_free=%u hugepages_surp=%u hugepages_size=%lukB\n",
index 91d67eaee0500796c9e5569fedc7cc5775002dda..8d2fcdfeff7fdb319f58c838cd8b94a6cc59121e 100644 (file)
@@ -1775,10 +1775,9 @@ void __init kmemleak_init(void)
        int i;
        unsigned long flags;
 
-       kmemleak_early_log = 0;
-
 #ifdef CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF
        if (!kmemleak_skip_disable) {
+               kmemleak_early_log = 0;
                kmemleak_disable();
                return;
        }
@@ -1796,6 +1795,7 @@ void __init kmemleak_init(void)
 
        /* the kernel is still in UP mode, so disabling the IRQs is enough */
        local_irq_save(flags);
+       kmemleak_early_log = 0;
        if (kmemleak_error) {
                local_irq_restore(flags);
                return;
index 539eeb96b323bf649f83783e0dddcb4f907e1d6e..a402f8fdc68e94888ea177104524085c9f490fd5 100644 (file)
@@ -195,7 +195,7 @@ static void force_shm_swapin_readahead(struct vm_area_struct *vma,
        for (; start < end; start += PAGE_SIZE) {
                index = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
 
-               page = find_get_page(mapping, index);
+               page = find_get_entry(mapping, index);
                if (!radix_tree_exceptional_entry(page)) {
                        if (page)
                                page_cache_release(page);
index 29501f04056887297be694c315c7caf3adf666f5..5177c6d4a2ddbf6d28ece095287c1a4a36ef9a2a 100644 (file)
@@ -1077,9 +1077,18 @@ static struct mem_cgroup *get_mem_cgroup_from_mm(struct mm_struct *mm)
 
        rcu_read_lock();
        do {
-               memcg = mem_cgroup_from_task(rcu_dereference(mm->owner));
-               if (unlikely(!memcg))
+               /*
+                * Page cache insertions can happen withou an
+                * actual mm context, e.g. during disk probing
+                * on boot, loopback IO, acct() writes etc.
+                */
+               if (unlikely(!mm))
                        memcg = root_mem_cgroup;
+               else {
+                       memcg = mem_cgroup_from_task(rcu_dereference(mm->owner));
+                       if (unlikely(!memcg))
+                               memcg = root_mem_cgroup;
+               }
        } while (!css_tryget(&memcg->css));
        rcu_read_unlock();
        return memcg;
@@ -3958,17 +3967,9 @@ int mem_cgroup_charge_file(struct page *page, struct mm_struct *mm,
                return 0;
        }
 
-       /*
-        * Page cache insertions can happen without an actual mm
-        * context, e.g. during disk probing on boot.
-        */
-       if (unlikely(!mm))
-               memcg = root_mem_cgroup;
-       else {
-               memcg = mem_cgroup_try_charge_mm(mm, gfp_mask, 1, true);
-               if (!memcg)
-                       return -ENOMEM;
-       }
+       memcg = mem_cgroup_try_charge_mm(mm, gfp_mask, 1, true);
+       if (!memcg)
+               return -ENOMEM;
        __mem_cgroup_commit_charge(memcg, page, 1, type, false);
        return 0;
 }
@@ -6686,16 +6687,20 @@ static struct page *mc_handle_file_pte(struct vm_area_struct *vma,
                pgoff = pte_to_pgoff(ptent);
 
        /* page is moved even if it's not RSS of this task(page-faulted). */
-       page = find_get_page(mapping, pgoff);
-
 #ifdef CONFIG_SWAP
        /* shmem/tmpfs may report page out on swap: account for that too. */
-       if (radix_tree_exceptional_entry(page)) {
-               swp_entry_t swap = radix_to_swp_entry(page);
-               if (do_swap_account)
-                       *entry = swap;
-               page = find_get_page(swap_address_space(swap), swap.val);
-       }
+       if (shmem_mapping(mapping)) {
+               page = find_get_entry(mapping, pgoff);
+               if (radix_tree_exceptional_entry(page)) {
+                       swp_entry_t swp = radix_to_swp_entry(page);
+                       if (do_swap_account)
+                               *entry = swp;
+                       page = find_get_page(swap_address_space(swp), swp.val);
+               }
+       } else
+               page = find_get_page(mapping, pgoff);
+#else
+       page = find_get_page(mapping, pgoff);
 #endif
        return page;
 }
index 35ef28acf137c0ab76393ede3dbc1c3d820f5c37..9ccef39a9de261c96f4e5775d7dca48b63d4d133 100644 (file)
@@ -1081,15 +1081,16 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
                        return 0;
                } else if (PageHuge(hpage)) {
                        /*
-                        * Check "just unpoisoned", "filter hit", and
-                        * "race with other subpage."
+                        * Check "filter hit" and "race with other subpage."
                         */
                        lock_page(hpage);
-                       if (!PageHWPoison(hpage)
-                           || (hwpoison_filter(p) && TestClearPageHWPoison(p))
-                           || (p != hpage && TestSetPageHWPoison(hpage))) {
-                               atomic_long_sub(nr_pages, &num_poisoned_pages);
-                               return 0;
+                       if (PageHWPoison(hpage)) {
+                               if ((hwpoison_filter(p) && TestClearPageHWPoison(p))
+                                   || (p != hpage && TestSetPageHWPoison(hpage))) {
+                                       atomic_long_sub(nr_pages, &num_poisoned_pages);
+                                       unlock_page(hpage);
+                                       return 0;
+                               }
                        }
                        set_page_hwpoison_huge_page(hpage);
                        res = dequeue_hwpoisoned_huge_page(hpage);
@@ -1152,6 +1153,8 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
         */
        if (!PageHWPoison(p)) {
                printk(KERN_ERR "MCE %#lx: just unpoisoned\n", pfn);
+               atomic_long_sub(nr_pages, &num_poisoned_pages);
+               put_page(hpage);
                res = 0;
                goto out;
        }
index 0843feb66f3d0236abd4386b5bfd0170c24ae0ef..05f1180e9f21822e99a5f11a2a7a03af663a422c 100644 (file)
@@ -194,10 +194,17 @@ unsigned long move_page_tables(struct vm_area_struct *vma,
                        break;
                if (pmd_trans_huge(*old_pmd)) {
                        int err = 0;
-                       if (extent == HPAGE_PMD_SIZE)
+                       if (extent == HPAGE_PMD_SIZE) {
+                               VM_BUG_ON(vma->vm_file || !vma->anon_vma);
+                               /* See comment in move_ptes() */
+                               if (need_rmap_locks)
+                                       anon_vma_lock_write(vma->anon_vma);
                                err = move_huge_pmd(vma, new_vma, old_addr,
                                                    new_addr, old_end,
                                                    old_pmd, new_pmd);
+                               if (need_rmap_locks)
+                                       anon_vma_unlock_write(vma->anon_vma);
+                       }
                        if (err > 0) {
                                need_flush = true;
                                continue;
index ef413492a14945c5e7ab0f5a8d33bd66eaf34873..a4317da60532be3eccb1c1e604362b3923271f65 100644 (file)
@@ -593,14 +593,14 @@ unsigned long bdi_dirty_limit(struct backing_dev_info *bdi, unsigned long dirty)
  * (5) the closer to setpoint, the smaller |df/dx| (and the reverse)
  *     => fast response on large errors; small oscillation near setpoint
  */
-static inline long long pos_ratio_polynom(unsigned long setpoint,
+static long long pos_ratio_polynom(unsigned long setpoint,
                                          unsigned long dirty,
                                          unsigned long limit)
 {
        long long pos_ratio;
        long x;
 
-       x = div_s64(((s64)setpoint - (s64)dirty) << RATELIMIT_CALC_SHIFT,
+       x = div64_s64(((s64)setpoint - (s64)dirty) << RATELIMIT_CALC_SHIFT,
                    limit - setpoint + 1);
        pos_ratio = x;
        pos_ratio = pos_ratio * x >> RATELIMIT_CALC_SHIFT;
@@ -842,7 +842,7 @@ static unsigned long bdi_position_ratio(struct backing_dev_info *bdi,
        x_intercept = bdi_setpoint + span;
 
        if (bdi_dirty < x_intercept - span / 4) {
-               pos_ratio = div_u64(pos_ratio * (x_intercept - bdi_dirty),
+               pos_ratio = div64_u64(pos_ratio * (x_intercept - bdi_dirty),
                                    x_intercept - bdi_setpoint + 1);
        } else
                pos_ratio /= 4;
index 63e24fb4387b6d305960f9e7ba8c0554e6818ca5..2ddf9a990dbd057228782a3af5ac6901a0af632b 100644 (file)
@@ -610,7 +610,7 @@ static struct pcpu_chunk *pcpu_alloc_chunk(void)
        chunk->map = pcpu_mem_zalloc(PCPU_DFL_MAP_ALLOC *
                                                sizeof(chunk->map[0]));
        if (!chunk->map) {
-               kfree(chunk);
+               pcpu_mem_free(chunk, pcpu_chunk_struct_size);
                return NULL;
        }
 
index 388cb1ae6fbc4907e6f0c6776b652adb5d055fe7..19d92181ce24917f799f5f6bbd46dada145d32d8 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -166,7 +166,7 @@ typedef unsigned char freelist_idx_t;
 typedef unsigned short freelist_idx_t;
 #endif
 
-#define SLAB_OBJ_MAX_NUM (1 << sizeof(freelist_idx_t) * BITS_PER_BYTE)
+#define SLAB_OBJ_MAX_NUM ((1 << sizeof(freelist_idx_t) * BITS_PER_BYTE) - 1)
 
 /*
  * true if a page was allocated from pfmemalloc reserves for network-based
@@ -2572,13 +2572,13 @@ static void *alloc_slabmgmt(struct kmem_cache *cachep,
        return freelist;
 }
 
-static inline freelist_idx_t get_free_obj(struct page *page, unsigned char idx)
+static inline freelist_idx_t get_free_obj(struct page *page, unsigned int idx)
 {
        return ((freelist_idx_t *)page->freelist)[idx];
 }
 
 static inline void set_free_obj(struct page *page,
-                                       unsigned char idx, freelist_idx_t val)
+                                       unsigned int idx, freelist_idx_t val)
 {
        ((freelist_idx_t *)(page->freelist))[idx] = val;
 }
index 3045316b7c9df285e04b3954c1921f7542f2311a..6bd4c353704ffd842f29ce9d6adfb3437f829676 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -91,6 +91,7 @@ __kmem_cache_alias(const char *name, size_t size, size_t align,
 #define CACHE_CREATE_MASK (SLAB_CORE_FLAGS | SLAB_DEBUG_FLAGS | SLAB_CACHE_FLAGS)
 
 int __kmem_cache_shutdown(struct kmem_cache *);
+void slab_kmem_cache_release(struct kmem_cache *);
 
 struct seq_file;
 struct file;
index f3cfccf76dda693250106d3c8d0387292e741c14..102cc6fca3d393f374984a7628d644b99b629a54 100644 (file)
@@ -323,6 +323,12 @@ static int kmem_cache_destroy_memcg_children(struct kmem_cache *s)
 }
 #endif /* CONFIG_MEMCG_KMEM */
 
+void slab_kmem_cache_release(struct kmem_cache *s)
+{
+       kfree(s->name);
+       kmem_cache_free(kmem_cache, s);
+}
+
 void kmem_cache_destroy(struct kmem_cache *s)
 {
        get_online_cpus();
@@ -352,8 +358,11 @@ void kmem_cache_destroy(struct kmem_cache *s)
                rcu_barrier();
 
        memcg_free_cache_params(s);
-       kfree(s->name);
-       kmem_cache_free(kmem_cache, s);
+#ifdef SLAB_SUPPORTS_SYSFS
+       sysfs_slab_remove(s);
+#else
+       slab_kmem_cache_release(s);
+#endif
        goto out_put_cpus;
 
 out_unlock:
index 5e234f1f8853e952dceefe8c6b92201fcc3853d7..2b1ce697fc4b4fc44d30ea3b1770ae1bea38d25e 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -210,14 +210,11 @@ enum track_item { TRACK_ALLOC, TRACK_FREE };
 #ifdef CONFIG_SYSFS
 static int sysfs_slab_add(struct kmem_cache *);
 static int sysfs_slab_alias(struct kmem_cache *, const char *);
-static void sysfs_slab_remove(struct kmem_cache *);
 static void memcg_propagate_slab_attrs(struct kmem_cache *s);
 #else
 static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; }
 static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p)
                                                        { return 0; }
-static inline void sysfs_slab_remove(struct kmem_cache *s) { }
-
 static inline void memcg_propagate_slab_attrs(struct kmem_cache *s) { }
 #endif
 
@@ -3238,24 +3235,7 @@ static inline int kmem_cache_close(struct kmem_cache *s)
 
 int __kmem_cache_shutdown(struct kmem_cache *s)
 {
-       int rc = kmem_cache_close(s);
-
-       if (!rc) {
-               /*
-                * Since slab_attr_store may take the slab_mutex, we should
-                * release the lock while removing the sysfs entry in order to
-                * avoid a deadlock. Because this is pretty much the last
-                * operation we do and the lock will be released shortly after
-                * that in slab_common.c, we could just move sysfs_slab_remove
-                * to a later point in common code. We should do that when we
-                * have a common sysfs framework for all allocators.
-                */
-               mutex_unlock(&slab_mutex);
-               sysfs_slab_remove(s);
-               mutex_lock(&slab_mutex);
-       }
-
-       return rc;
+       return kmem_cache_close(s);
 }
 
 /********************************************************************
@@ -5071,15 +5051,18 @@ static void memcg_propagate_slab_attrs(struct kmem_cache *s)
 #ifdef CONFIG_MEMCG_KMEM
        int i;
        char *buffer = NULL;
+       struct kmem_cache *root_cache;
 
-       if (!is_root_cache(s))
+       if (is_root_cache(s))
                return;
 
+       root_cache = s->memcg_params->root_cache;
+
        /*
         * This mean this cache had no attribute written. Therefore, no point
         * in copying default values around
         */
-       if (!s->max_attr_size)
+       if (!root_cache->max_attr_size)
                return;
 
        for (i = 0; i < ARRAY_SIZE(slab_attrs); i++) {
@@ -5101,7 +5084,7 @@ static void memcg_propagate_slab_attrs(struct kmem_cache *s)
                 */
                if (buffer)
                        buf = buffer;
-               else if (s->max_attr_size < ARRAY_SIZE(mbuf))
+               else if (root_cache->max_attr_size < ARRAY_SIZE(mbuf))
                        buf = mbuf;
                else {
                        buffer = (char *) get_zeroed_page(GFP_KERNEL);
@@ -5110,7 +5093,7 @@ static void memcg_propagate_slab_attrs(struct kmem_cache *s)
                        buf = buffer;
                }
 
-               attr->show(s->memcg_params->root_cache, buf);
+               attr->show(root_cache, buf);
                attr->store(s, buf, strlen(buf));
        }
 
@@ -5119,6 +5102,11 @@ static void memcg_propagate_slab_attrs(struct kmem_cache *s)
 #endif
 }
 
+static void kmem_cache_release(struct kobject *k)
+{
+       slab_kmem_cache_release(to_slab(k));
+}
+
 static const struct sysfs_ops slab_sysfs_ops = {
        .show = slab_attr_show,
        .store = slab_attr_store,
@@ -5126,6 +5114,7 @@ static const struct sysfs_ops slab_sysfs_ops = {
 
 static struct kobj_type slab_ktype = {
        .sysfs_ops = &slab_sysfs_ops,
+       .release = kmem_cache_release,
 };
 
 static int uevent_filter(struct kset *kset, struct kobject *kobj)
@@ -5252,7 +5241,7 @@ out_put_kobj:
        goto out;
 }
 
-static void sysfs_slab_remove(struct kmem_cache *s)
+void sysfs_slab_remove(struct kmem_cache *s)
 {
        if (slab_state < FULL)
                /*
index e5cc39ab0751f08b30691c3e7e8c98e32ded409c..6a78c814bebfb151b1e490424c731edc172ad430 100644 (file)
@@ -484,14 +484,6 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping,
        unsigned long count = 0;
        int i;
 
-       /*
-        * Note: this function may get called on a shmem/tmpfs mapping:
-        * pagevec_lookup() might then return 0 prematurely (because it
-        * got a gangful of swap entries); but it's hardly worth worrying
-        * about - it can rarely have anything to free from such a mapping
-        * (most pages are dirty), and already skips over any difficulties.
-        */
-
        pagevec_init(&pvec, 0);
        while (index <= end && pagevec_lookup_entries(&pvec, mapping, index,
                        min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1,
index f380af7ea7797e287b222cd57b665fad02b6132e..d5ea733c508265aaba619248d973ec640a73d04a 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -10,6 +10,7 @@
 #include <linux/swapops.h>
 #include <linux/mman.h>
 #include <linux/hugetlb.h>
+#include <linux/vmalloc.h>
 
 #include <asm/uaccess.h>
 
@@ -387,6 +388,15 @@ unsigned long vm_mmap(struct file *file, unsigned long addr,
 }
 EXPORT_SYMBOL(vm_mmap);
 
+void kvfree(const void *addr)
+{
+       if (is_vmalloc_addr(addr))
+               vfree(addr);
+       else
+               kfree(addr);
+}
+EXPORT_SYMBOL(kvfree);
+
 struct address_space *page_mapping(struct page *page)
 {
        struct address_space *mapping = page->mapping;
index 3f56c8deb3c05f0904917b87113e188dbeff9ef0..32c661d66a45498e270ba5e9019cda60a114cc27 100644 (file)
@@ -1915,6 +1915,24 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
        file  = get_lru_size(lruvec, LRU_ACTIVE_FILE) +
                get_lru_size(lruvec, LRU_INACTIVE_FILE);
 
+       /*
+        * Prevent the reclaimer from falling into the cache trap: as
+        * cache pages start out inactive, every cache fault will tip
+        * the scan balance towards the file LRU.  And as the file LRU
+        * shrinks, so does the window for rotation from references.
+        * This means we have a runaway feedback loop where a tiny
+        * thrashing file LRU becomes infinitely more attractive than
+        * anon pages.  Try to detect this based on file LRU size.
+        */
+       if (global_reclaim(sc)) {
+               unsigned long free = zone_page_state(zone, NR_FREE_PAGES);
+
+               if (unlikely(file + free <= high_wmark_pages(zone))) {
+                       scan_balance = SCAN_ANON;
+                       goto out;
+               }
+       }
+
        /*
         * There is enough inactive page cache, do not reclaim
         * anything from the anonymous working set right now.
index 175273f38cb1bd59f5aeb88cb8c815033475dfe8..44ebd5c2cd4aef0f86bd6475132cc40c501c6fef 100644 (file)
@@ -169,6 +169,7 @@ int register_vlan_dev(struct net_device *dev)
        if (err < 0)
                goto out_uninit_mvrp;
 
+       vlan->nest_level = dev_get_nest_level(real_dev, is_vlan_dev) + 1;
        err = register_netdevice(dev);
        if (err < 0)
                goto out_uninit_mvrp;
index 733ec283ed1b9e85f9181f67116052f88bb49951..019efb79708f81976bc6484cc371a8fa6c0c080e 100644 (file)
@@ -493,48 +493,10 @@ static void vlan_dev_change_rx_flags(struct net_device *dev, int change)
        }
 }
 
-static int vlan_calculate_locking_subclass(struct net_device *real_dev)
-{
-       int subclass = 0;
-
-       while (is_vlan_dev(real_dev)) {
-               subclass++;
-               real_dev = vlan_dev_priv(real_dev)->real_dev;
-       }
-
-       return subclass;
-}
-
-static void vlan_dev_mc_sync(struct net_device *to, struct net_device *from)
-{
-       int err = 0, subclass;
-
-       subclass = vlan_calculate_locking_subclass(to);
-
-       spin_lock_nested(&to->addr_list_lock, subclass);
-       err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len);
-       if (!err)
-               __dev_set_rx_mode(to);
-       spin_unlock(&to->addr_list_lock);
-}
-
-static void vlan_dev_uc_sync(struct net_device *to, struct net_device *from)
-{
-       int err = 0, subclass;
-
-       subclass = vlan_calculate_locking_subclass(to);
-
-       spin_lock_nested(&to->addr_list_lock, subclass);
-       err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len);
-       if (!err)
-               __dev_set_rx_mode(to);
-       spin_unlock(&to->addr_list_lock);
-}
-
 static void vlan_dev_set_rx_mode(struct net_device *vlan_dev)
 {
-       vlan_dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev);
-       vlan_dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev);
+       dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev);
+       dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev);
 }
 
 /*
@@ -562,6 +524,11 @@ static void vlan_dev_set_lockdep_class(struct net_device *dev, int subclass)
        netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, &subclass);
 }
 
+static int vlan_dev_get_lock_subclass(struct net_device *dev)
+{
+       return vlan_dev_priv(dev)->nest_level;
+}
+
 static const struct header_ops vlan_header_ops = {
        .create  = vlan_dev_hard_header,
        .rebuild = vlan_dev_rebuild_header,
@@ -597,7 +564,6 @@ static const struct net_device_ops vlan_netdev_ops;
 static int vlan_dev_init(struct net_device *dev)
 {
        struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
-       int subclass = 0;
 
        netif_carrier_off(dev);
 
@@ -646,8 +612,7 @@ static int vlan_dev_init(struct net_device *dev)
 
        SET_NETDEV_DEVTYPE(dev, &vlan_type);
 
-       subclass = vlan_calculate_locking_subclass(dev);
-       vlan_dev_set_lockdep_class(dev, subclass);
+       vlan_dev_set_lockdep_class(dev, vlan_dev_get_lock_subclass(dev));
 
        vlan_dev_priv(dev)->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats);
        if (!vlan_dev_priv(dev)->vlan_pcpu_stats)
@@ -819,6 +784,7 @@ static const struct net_device_ops vlan_netdev_ops = {
        .ndo_netpoll_cleanup    = vlan_dev_netpoll_cleanup,
 #endif
        .ndo_fix_features       = vlan_dev_fix_features,
+       .ndo_get_lock_subclass  = vlan_dev_get_lock_subclass,
 };
 
 void vlan_setup(struct net_device *dev)
index b3bd4ec3fd9452f0d1f9a99dd4782260ab65c818..f04224c32005aa9a732622805915fe9aead9ee3e 100644 (file)
@@ -1545,6 +1545,8 @@ out_neigh:
        if ((orig_neigh_node) && (!is_single_hop_neigh))
                batadv_orig_node_free_ref(orig_neigh_node);
 out:
+       if (router_ifinfo)
+               batadv_neigh_ifinfo_free_ref(router_ifinfo);
        if (router)
                batadv_neigh_node_free_ref(router);
        if (router_router)
index b25fd64d727b0d6e8227671f860b133095df5100..aa5d4946d0d784d32fdcdce217c4f2bb482502f0 100644 (file)
@@ -940,8 +940,7 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
                 * additional DAT answer may trigger kernel warnings about
                 * a packet coming from the wrong port.
                 */
-               if (batadv_is_my_client(bat_priv, dat_entry->mac_addr,
-                                       BATADV_NO_FLAGS)) {
+               if (batadv_is_my_client(bat_priv, dat_entry->mac_addr, vid)) {
                        ret = true;
                        goto out;
                }
index bcc4bea632fa69ead6567e016f2f265840f7968b..f14e54a0569178e8b423b4921c4b610e4c63039c 100644 (file)
@@ -418,12 +418,13 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
                             struct batadv_neigh_node *neigh_node)
 {
        struct batadv_priv *bat_priv;
-       struct batadv_hard_iface *primary_if;
+       struct batadv_hard_iface *primary_if = NULL;
        struct batadv_frag_packet frag_header;
        struct sk_buff *skb_fragment;
        unsigned mtu = neigh_node->if_incoming->net_dev->mtu;
        unsigned header_size = sizeof(frag_header);
        unsigned max_fragment_size, max_packet_size;
+       bool ret = false;
 
        /* To avoid merge and refragmentation at next-hops we never send
         * fragments larger than BATADV_FRAG_MAX_FRAG_SIZE
@@ -483,7 +484,11 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
                           skb->len + ETH_HLEN);
        batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
 
-       return true;
+       ret = true;
+
 out_err:
-       return false;
+       if (primary_if)
+               batadv_hardif_free_ref(primary_if);
+
+       return ret;
 }
index c835e137423bb9ec70b98b5130d5a33c12f9b139..90cff585b37d5a3779cdb8f7b3b90a26eb2df88e 100644 (file)
 
 static void batadv_gw_node_free_ref(struct batadv_gw_node *gw_node)
 {
-       if (atomic_dec_and_test(&gw_node->refcount))
+       if (atomic_dec_and_test(&gw_node->refcount)) {
+               batadv_orig_node_free_ref(gw_node->orig_node);
                kfree_rcu(gw_node, rcu);
+       }
 }
 
 static struct batadv_gw_node *
@@ -406,9 +408,14 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
        if (gateway->bandwidth_down == 0)
                return;
 
+       if (!atomic_inc_not_zero(&orig_node->refcount))
+               return;
+
        gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC);
-       if (!gw_node)
+       if (!gw_node) {
+               batadv_orig_node_free_ref(orig_node);
                return;
+       }
 
        INIT_HLIST_NODE(&gw_node->list);
        gw_node->orig_node = orig_node;
index b851cc58085330acbab02848fedf3cb01751a060..fbda6b54baffccf798375cb8add49bb179738386 100644 (file)
@@ -83,7 +83,7 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
                return true;
 
        /* no more parents..stop recursion */
-       if (net_dev->iflink == net_dev->ifindex)
+       if (net_dev->iflink == 0 || net_dev->iflink == net_dev->ifindex)
                return false;
 
        /* recurse over the parent device */
index ffd9dfbd9b0e856e35e2ac6ea594739e8feb614d..6a484514cd3e98b9e0b27a924b4dcb92f2682055 100644 (file)
@@ -501,12 +501,17 @@ batadv_neigh_node_get(const struct batadv_orig_node *orig_node,
 static void batadv_orig_ifinfo_free_rcu(struct rcu_head *rcu)
 {
        struct batadv_orig_ifinfo *orig_ifinfo;
+       struct batadv_neigh_node *router;
 
        orig_ifinfo = container_of(rcu, struct batadv_orig_ifinfo, rcu);
 
        if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT)
                batadv_hardif_free_ref_now(orig_ifinfo->if_outgoing);
 
+       /* this is the last reference to this object */
+       router = rcu_dereference_protected(orig_ifinfo->router, true);
+       if (router)
+               batadv_neigh_node_free_ref_now(router);
        kfree(orig_ifinfo);
 }
 
@@ -701,6 +706,47 @@ free_orig_node:
        return NULL;
 }
 
+/**
+ * batadv_purge_neigh_ifinfo - purge obsolete ifinfo entries from neighbor
+ * @bat_priv: the bat priv with all the soft interface information
+ * @neigh: orig node which is to be checked
+ */
+static void
+batadv_purge_neigh_ifinfo(struct batadv_priv *bat_priv,
+                         struct batadv_neigh_node *neigh)
+{
+       struct batadv_neigh_ifinfo *neigh_ifinfo;
+       struct batadv_hard_iface *if_outgoing;
+       struct hlist_node *node_tmp;
+
+       spin_lock_bh(&neigh->ifinfo_lock);
+
+       /* for all ifinfo objects for this neighinator */
+       hlist_for_each_entry_safe(neigh_ifinfo, node_tmp,
+                                 &neigh->ifinfo_list, list) {
+               if_outgoing = neigh_ifinfo->if_outgoing;
+
+               /* always keep the default interface */
+               if (if_outgoing == BATADV_IF_DEFAULT)
+                       continue;
+
+               /* don't purge if the interface is not (going) down */
+               if ((if_outgoing->if_status != BATADV_IF_INACTIVE) &&
+                   (if_outgoing->if_status != BATADV_IF_NOT_IN_USE) &&
+                   (if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED))
+                       continue;
+
+               batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
+                          "neighbor/ifinfo purge: neighbor %pM, iface: %s\n",
+                          neigh->addr, if_outgoing->net_dev->name);
+
+               hlist_del_rcu(&neigh_ifinfo->list);
+               batadv_neigh_ifinfo_free_ref(neigh_ifinfo);
+       }
+
+       spin_unlock_bh(&neigh->ifinfo_lock);
+}
+
 /**
  * batadv_purge_orig_ifinfo - purge obsolete ifinfo entries from originator
  * @bat_priv: the bat priv with all the soft interface information
@@ -800,6 +846,11 @@ batadv_purge_orig_neighbors(struct batadv_priv *bat_priv,
 
                        hlist_del_rcu(&neigh_node->list);
                        batadv_neigh_node_free_ref(neigh_node);
+               } else {
+                       /* only necessary if not the whole neighbor is to be
+                        * deleted, but some interface has been removed.
+                        */
+                       batadv_purge_neigh_ifinfo(bat_priv, neigh_node);
                }
        }
 
@@ -857,7 +908,7 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
 {
        struct batadv_neigh_node *best_neigh_node;
        struct batadv_hard_iface *hard_iface;
-       bool changed;
+       bool changed_ifinfo, changed_neigh;
 
        if (batadv_has_timed_out(orig_node->last_seen,
                                 2 * BATADV_PURGE_TIMEOUT)) {
@@ -867,10 +918,10 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv,
                           jiffies_to_msecs(orig_node->last_seen));
                return true;
        }
-       changed = batadv_purge_orig_ifinfo(bat_priv, orig_node);
-       changed = changed || batadv_purge_orig_neighbors(bat_priv, orig_node);
+       changed_ifinfo = batadv_purge_orig_ifinfo(bat_priv, orig_node);
+       changed_neigh = batadv_purge_orig_neighbors(bat_priv, orig_node);
 
-       if (!changed)
+       if (!changed_ifinfo && !changed_neigh)
                return false;
 
        /* first for NULL ... */
@@ -1028,7 +1079,8 @@ int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset)
        bat_priv->bat_algo_ops->bat_orig_print(bat_priv, seq, hard_iface);
 
 out:
-       batadv_hardif_free_ref(hard_iface);
+       if (hard_iface)
+               batadv_hardif_free_ref(hard_iface);
        return 0;
 }
 
index d958e2dca52fa5bb4d166e0073fa90d18729a73f..521fd4f3985e11aef05880be5307b632a46afc53 100644 (file)
@@ -819,14 +819,17 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
        if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
                struct hci_cp_auth_requested cp;
 
-               /* encrypt must be pending if auth is also pending */
-               set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
-
                cp.handle = cpu_to_le16(conn->handle);
                hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
                             sizeof(cp), &cp);
+
+               /* If we're already encrypted set the REAUTH_PEND flag,
+                * otherwise set the ENCRYPT_PEND.
+                */
                if (conn->key_type != 0xff)
                        set_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
+               else
+                       set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
        }
 
        return 0;
index 49774912cb01f23ef6f85cb26f8613f538edec94..15010a230b6d5fdf08bb9cd91d7b0ac5aee25c61 100644 (file)
@@ -3330,6 +3330,12 @@ static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
        if (!conn)
                goto unlock;
 
+       /* For BR/EDR the necessary steps are taken through the
+        * auth_complete event.
+        */
+       if (conn->type != LE_LINK)
+               goto unlock;
+
        if (!ev->status)
                conn->sec_level = conn->pending_sec_level;
 
index 80e1b0f60a30214002684a42b1bab1a02e9d9962..2acf7fa1fec6c2309123dc189ea964f66f230d07 100644 (file)
@@ -859,12 +859,12 @@ static unsigned int br_nf_forward_arp(const struct nf_hook_ops *ops,
        return NF_STOLEN;
 }
 
-#if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV4)
+#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4)
 static int br_nf_dev_queue_xmit(struct sk_buff *skb)
 {
        int ret;
 
-       if (skb->nfct != NULL && skb->protocol == htons(ETH_P_IP) &&
+       if (skb->protocol == htons(ETH_P_IP) &&
            skb->len + nf_bridge_mtu_reduction(skb) > skb->dev->mtu &&
            !skb_is_gso(skb)) {
                if (br_parse_ip_options(skb))
index e74b6d530cb6a3ab3dc650ee1900df06d3b3441a..e8844d975b321ac4e3f6a0cca76035918ec93a1b 100644 (file)
@@ -445,6 +445,20 @@ static int br_validate(struct nlattr *tb[], struct nlattr *data[])
        return 0;
 }
 
+static int br_dev_newlink(struct net *src_net, struct net_device *dev,
+                         struct nlattr *tb[], struct nlattr *data[])
+{
+       struct net_bridge *br = netdev_priv(dev);
+
+       if (tb[IFLA_ADDRESS]) {
+               spin_lock_bh(&br->lock);
+               br_stp_change_bridge_id(br, nla_data(tb[IFLA_ADDRESS]));
+               spin_unlock_bh(&br->lock);
+       }
+
+       return register_netdevice(dev);
+}
+
 static size_t br_get_link_af_size(const struct net_device *dev)
 {
        struct net_port_vlans *pv;
@@ -473,6 +487,7 @@ struct rtnl_link_ops br_link_ops __read_mostly = {
        .priv_size      = sizeof(struct net_bridge),
        .setup          = br_dev_setup,
        .validate       = br_validate,
+       .newlink        = br_dev_newlink,
        .dellink        = br_dev_delete,
 };
 
index ac31891967da1ed811247d131dffbabfd7d28d11..050a2110d43f6b78f331b599569eaaf2d8803c24 100644 (file)
@@ -804,7 +804,7 @@ static int cgw_create_job(struct sk_buff *skb,  struct nlmsghdr *nlh)
        u8 limhops = 0;
        int err = 0;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
        if (nlmsg_len(nlh) < sizeof(*r))
@@ -893,7 +893,7 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh)
        u8 limhops = 0;
        int err = 0;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
        if (nlmsg_len(nlh) < sizeof(*r))
index dac7f9b986877efa88f8e308e783c216563ad243..1948d592aa54c7a1831df546702904898cd68da4 100644 (file)
@@ -557,7 +557,7 @@ static int ceph_tcp_sendmsg(struct socket *sock, struct kvec *iov,
        return r;
 }
 
-static int ceph_tcp_sendpage(struct socket *sock, struct page *page,
+static int __ceph_tcp_sendpage(struct socket *sock, struct page *page,
                     int offset, size_t size, bool more)
 {
        int flags = MSG_DONTWAIT | MSG_NOSIGNAL | (more ? MSG_MORE : MSG_EOR);
@@ -570,6 +570,24 @@ static int ceph_tcp_sendpage(struct socket *sock, struct page *page,
        return ret;
 }
 
+static int ceph_tcp_sendpage(struct socket *sock, struct page *page,
+                    int offset, size_t size, bool more)
+{
+       int ret;
+       struct kvec iov;
+
+       /* sendpage cannot properly handle pages with page_count == 0,
+        * we need to fallback to sendmsg if that's the case */
+       if (page_count(page) >= 1)
+               return __ceph_tcp_sendpage(sock, page, offset, size, more);
+
+       iov.iov_base = kmap(page) + offset;
+       iov.iov_len = size;
+       ret = ceph_tcp_sendmsg(sock, &iov, 1, size, more);
+       kunmap(page);
+
+       return ret;
+}
 
 /*
  * Shutdown/close the socket for the given connection.
index e632b5a52f5b89cb2e275b64494905cc7ebfc8e7..c547e46084d360c14abd34f97b6d1d3592d1c641 100644 (file)
@@ -329,6 +329,11 @@ static struct crush_map *crush_decode(void *pbyval, void *end)
        dout("crush decode tunable chooseleaf_descend_once = %d",
             c->chooseleaf_descend_once);
 
+       ceph_decode_need(p, end, sizeof(u8), done);
+       c->chooseleaf_vary_r = ceph_decode_8(p);
+       dout("crush decode tunable chooseleaf_vary_r = %d",
+            c->chooseleaf_vary_r);
+
 done:
        dout("crush_decode success\n");
        return c;
@@ -1548,8 +1553,10 @@ static void apply_primary_affinity(struct ceph_osdmap *osdmap, u32 pps,
                return;
 
        for (i = 0; i < len; i++) {
-               if (osds[i] != CRUSH_ITEM_NONE &&
-                   osdmap->osd_primary_affinity[i] !=
+               int osd = osds[i];
+
+               if (osd != CRUSH_ITEM_NONE &&
+                   osdmap->osd_primary_affinity[osd] !=
                                        CEPH_OSD_DEFAULT_PRIMARY_AFFINITY) {
                        break;
                }
@@ -1563,10 +1570,9 @@ static void apply_primary_affinity(struct ceph_osdmap *osdmap, u32 pps,
         * osd's pgs get rejected as primary.
         */
        for (i = 0; i < len; i++) {
-               int osd;
+               int osd = osds[i];
                u32 aff;
 
-               osd = osds[i];
                if (osd == CRUSH_ITEM_NONE)
                        continue;
 
index d2c8a06b3a9883b618c55a8cddf0929a4bcd049f..9abc503b19b7dad367b83a8179468ee3e1ae72d5 100644 (file)
@@ -2418,7 +2418,7 @@ EXPORT_SYMBOL(netdev_rx_csum_fault);
  * 2. No high memory really exists on this machine.
  */
 
-static int illegal_highdma(const struct net_device *dev, struct sk_buff *skb)
+static int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
 {
 #ifdef CONFIG_HIGHMEM
        int i;
@@ -2493,38 +2493,36 @@ static int dev_gso_segment(struct sk_buff *skb, netdev_features_t features)
 }
 
 static netdev_features_t harmonize_features(struct sk_buff *skb,
-                                           const struct net_device *dev,
-                                           netdev_features_t features)
+       netdev_features_t features)
 {
        int tmp;
 
        if (skb->ip_summed != CHECKSUM_NONE &&
            !can_checksum_protocol(features, skb_network_protocol(skb, &tmp))) {
                features &= ~NETIF_F_ALL_CSUM;
-       } else if (illegal_highdma(dev, skb)) {
+       } else if (illegal_highdma(skb->dev, skb)) {
                features &= ~NETIF_F_SG;
        }
 
        return features;
 }
 
-netdev_features_t netif_skb_dev_features(struct sk_buff *skb,
-                                        const struct net_device *dev)
+netdev_features_t netif_skb_features(struct sk_buff *skb)
 {
        __be16 protocol = skb->protocol;
-       netdev_features_t features = dev->features;
+       netdev_features_t features = skb->dev->features;
 
-       if (skb_shinfo(skb)->gso_segs > dev->gso_max_segs)
+       if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs)
                features &= ~NETIF_F_GSO_MASK;
 
        if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) {
                struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
                protocol = veh->h_vlan_encapsulated_proto;
        } else if (!vlan_tx_tag_present(skb)) {
-               return harmonize_features(skb, dev, features);
+               return harmonize_features(skb, features);
        }
 
-       features &= (dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX |
+       features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX |
                                               NETIF_F_HW_VLAN_STAG_TX);
 
        if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD))
@@ -2532,9 +2530,9 @@ netdev_features_t netif_skb_dev_features(struct sk_buff *skb,
                                NETIF_F_GEN_CSUM | NETIF_F_HW_VLAN_CTAG_TX |
                                NETIF_F_HW_VLAN_STAG_TX;
 
-       return harmonize_features(skb, dev, features);
+       return harmonize_features(skb, features);
 }
-EXPORT_SYMBOL(netif_skb_dev_features);
+EXPORT_SYMBOL(netif_skb_features);
 
 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                        struct netdev_queue *txq)
@@ -3953,6 +3951,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
        }
        NAPI_GRO_CB(skb)->count = 1;
        NAPI_GRO_CB(skb)->age = jiffies;
+       NAPI_GRO_CB(skb)->last = skb;
        skb_shinfo(skb)->gso_size = skb_gro_len(skb);
        skb->next = napi->gro_list;
        napi->gro_list = skb;
@@ -4542,6 +4541,32 @@ void *netdev_adjacent_get_private(struct list_head *adj_list)
 }
 EXPORT_SYMBOL(netdev_adjacent_get_private);
 
+/**
+ * netdev_upper_get_next_dev_rcu - Get the next dev from upper list
+ * @dev: device
+ * @iter: list_head ** of the current position
+ *
+ * Gets the next device from the dev's upper list, starting from iter
+ * position. The caller must hold RCU read lock.
+ */
+struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
+                                                struct list_head **iter)
+{
+       struct netdev_adjacent *upper;
+
+       WARN_ON_ONCE(!rcu_read_lock_held() && !lockdep_rtnl_is_held());
+
+       upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list);
+
+       if (&upper->list == &dev->adj_list.upper)
+               return NULL;
+
+       *iter = &upper->list;
+
+       return upper->dev;
+}
+EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu);
+
 /**
  * netdev_all_upper_get_next_dev_rcu - Get the next dev from upper list
  * @dev: device
@@ -4623,6 +4648,32 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev,
 }
 EXPORT_SYMBOL(netdev_lower_get_next_private_rcu);
 
+/**
+ * netdev_lower_get_next - Get the next device from the lower neighbour
+ *                         list
+ * @dev: device
+ * @iter: list_head ** of the current position
+ *
+ * Gets the next netdev_adjacent from the dev's lower neighbour
+ * list, starting from iter position. The caller must hold RTNL lock or
+ * its own locking that guarantees that the neighbour lower
+ * list will remain unchainged.
+ */
+void *netdev_lower_get_next(struct net_device *dev, struct list_head **iter)
+{
+       struct netdev_adjacent *lower;
+
+       lower = list_entry((*iter)->next, struct netdev_adjacent, list);
+
+       if (&lower->list == &dev->adj_list.lower)
+               return NULL;
+
+       *iter = &lower->list;
+
+       return lower->dev;
+}
+EXPORT_SYMBOL(netdev_lower_get_next);
+
 /**
  * netdev_lower_get_first_private_rcu - Get the first ->private from the
  *                                    lower neighbour list, RCU
@@ -5073,6 +5124,30 @@ void *netdev_lower_dev_get_private(struct net_device *dev,
 }
 EXPORT_SYMBOL(netdev_lower_dev_get_private);
 
+
+int dev_get_nest_level(struct net_device *dev,
+                      bool (*type_check)(struct net_device *dev))
+{
+       struct net_device *lower = NULL;
+       struct list_head *iter;
+       int max_nest = -1;
+       int nest;
+
+       ASSERT_RTNL();
+
+       netdev_for_each_lower_dev(dev, lower, iter) {
+               nest = dev_get_nest_level(lower, type_check);
+               if (max_nest < nest)
+                       max_nest = nest;
+       }
+
+       if (type_check(dev))
+               max_nest++;
+
+       return max_nest;
+}
+EXPORT_SYMBOL(dev_get_nest_level);
+
 static void dev_change_rx_flags(struct net_device *dev, int flags)
 {
        const struct net_device_ops *ops = dev->netdev_ops;
@@ -5238,7 +5313,6 @@ void __dev_set_rx_mode(struct net_device *dev)
        if (ops->ndo_set_rx_mode)
                ops->ndo_set_rx_mode(dev);
 }
-EXPORT_SYMBOL(__dev_set_rx_mode);
 
 void dev_set_rx_mode(struct net_device *dev)
 {
@@ -5543,7 +5617,7 @@ 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);
+DECLARE_WAIT_QUEUE_HEAD(netdev_unregistering_wq);
 
 static void net_set_todo(struct net_device *dev)
 {
index cd58614660cf54e1431392c5045bbdc9478336e6..9d79ca0a6e8e93e1bfc6d92c8a154a96ae0681c6 100644 (file)
@@ -122,6 +122,13 @@ noinline u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
        return 0;
 }
 
+/* Register mappings for user programs. */
+#define A_REG          0
+#define X_REG          7
+#define TMP_REG                8
+#define ARG2_REG       2
+#define ARG3_REG       3
+
 /**
  *     __sk_run_filter - run a filter on a given context
  *     @ctx: buffer to run the filter on
@@ -242,6 +249,8 @@ unsigned int __sk_run_filter(void *ctx, const struct sock_filter_int *insn)
 
        regs[FP_REG]  = (u64) (unsigned long) &stack[ARRAY_SIZE(stack)];
        regs[ARG1_REG] = (u64) (unsigned long) ctx;
+       regs[A_REG] = 0;
+       regs[X_REG] = 0;
 
 select_insn:
        goto *jumptable[insn->code];
@@ -643,13 +652,6 @@ static u64 __get_raw_cpu_id(u64 ctx, u64 A, u64 X, u64 r4, u64 r5)
        return raw_smp_processor_id();
 }
 
-/* Register mappings for user programs. */
-#define A_REG          0
-#define X_REG          7
-#define TMP_REG                8
-#define ARG2_REG       2
-#define ARG3_REG       3
-
 static bool convert_bpf_extensions(struct sock_filter *fp,
                                   struct sock_filter_int **insnp)
 {
index 8f8a96ef9f3f64ba519fe4c872d46c7b7c680ec9..32d872eec7f5c535221898cdb45ab8f235d0b4bb 100644 (file)
@@ -1248,8 +1248,8 @@ void __neigh_set_probe_once(struct neighbour *neigh)
        neigh->updated = jiffies;
        if (!(neigh->nud_state & NUD_FAILED))
                return;
-       neigh->nud_state = NUD_PROBE;
-       atomic_set(&neigh->probes, NEIGH_VAR(neigh->parms, UCAST_PROBES));
+       neigh->nud_state = NUD_INCOMPLETE;
+       atomic_set(&neigh->probes, neigh_max_probes(neigh));
        neigh_add_timer(neigh,
                        jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
 }
index 81d3a9a084536541867afe9350602c0c73253006..7c8ffd97496175c60d3947019bfd138bb9746938 100644 (file)
@@ -24,7 +24,7 @@
 
 static LIST_HEAD(pernet_list);
 static struct list_head *first_device = &pernet_list;
-static DEFINE_MUTEX(net_mutex);
+DEFINE_MUTEX(net_mutex);
 
 LIST_HEAD(net_namespace_list);
 EXPORT_SYMBOL_GPL(net_namespace_list);
index d4ff41739b0f23fcb572905dd34288cb1d8ebd49..2d8d8fcfa060c51e2f6cbe240aff3d01b3f964cc 100644 (file)
@@ -353,15 +353,46 @@ void __rtnl_link_unregister(struct rtnl_link_ops *ops)
 }
 EXPORT_SYMBOL_GPL(__rtnl_link_unregister);
 
+/* Return with the rtnl_lock held when there are no network
+ * devices unregistering in any network namespace.
+ */
+static void rtnl_lock_unregistering_all(void)
+{
+       struct net *net;
+       bool unregistering;
+       DEFINE_WAIT(wait);
+
+       for (;;) {
+               prepare_to_wait(&netdev_unregistering_wq, &wait,
+                               TASK_UNINTERRUPTIBLE);
+               unregistering = false;
+               rtnl_lock();
+               for_each_net(net) {
+                       if (net->dev_unreg_count > 0) {
+                               unregistering = true;
+                               break;
+                       }
+               }
+               if (!unregistering)
+                       break;
+               __rtnl_unlock();
+               schedule();
+       }
+       finish_wait(&netdev_unregistering_wq, &wait);
+}
+
 /**
  * rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
  * @ops: struct rtnl_link_ops * to unregister
  */
 void rtnl_link_unregister(struct rtnl_link_ops *ops)
 {
-       rtnl_lock();
+       /* Close the race with cleanup_net() */
+       mutex_lock(&net_mutex);
+       rtnl_lock_unregistering_all();
        __rtnl_link_unregister(ops);
        rtnl_unlock();
+       mutex_unlock(&net_mutex);
 }
 EXPORT_SYMBOL_GPL(rtnl_link_unregister);
 
@@ -774,7 +805,8 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev,
                return 0;
 }
 
-static size_t rtnl_port_size(const struct net_device *dev)
+static size_t rtnl_port_size(const struct net_device *dev,
+                            u32 ext_filter_mask)
 {
        size_t port_size = nla_total_size(4)            /* PORT_VF */
                + nla_total_size(PORT_PROFILE_MAX)      /* PORT_PROFILE */
@@ -790,7 +822,8 @@ static size_t rtnl_port_size(const struct net_device *dev)
        size_t port_self_size = nla_total_size(sizeof(struct nlattr))
                + port_size;
 
-       if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent)
+       if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent ||
+           !(ext_filter_mask & RTEXT_FILTER_VF))
                return 0;
        if (dev_num_vf(dev->dev.parent))
                return port_self_size + vf_ports_size +
@@ -826,7 +859,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
               + nla_total_size(ext_filter_mask
                                & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */
               + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */
-              + rtnl_port_size(dev) /* IFLA_VF_PORTS + IFLA_PORT_SELF */
+              + rtnl_port_size(dev, ext_filter_mask) /* IFLA_VF_PORTS + IFLA_PORT_SELF */
               + rtnl_link_get_size(dev) /* IFLA_LINKINFO */
               + rtnl_link_get_af_size(dev) /* IFLA_AF_SPEC */
               + nla_total_size(MAX_PHYS_PORT_ID_LEN); /* IFLA_PHYS_PORT_ID */
@@ -888,11 +921,13 @@ static int rtnl_port_self_fill(struct sk_buff *skb, struct net_device *dev)
        return 0;
 }
 
-static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev)
+static int rtnl_port_fill(struct sk_buff *skb, struct net_device *dev,
+                         u32 ext_filter_mask)
 {
        int err;
 
-       if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent)
+       if (!dev->netdev_ops->ndo_get_vf_port || !dev->dev.parent ||
+           !(ext_filter_mask & RTEXT_FILTER_VF))
                return 0;
 
        err = rtnl_port_self_fill(skb, dev);
@@ -1079,7 +1114,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                nla_nest_end(skb, vfinfo);
        }
 
-       if (rtnl_port_fill(skb, dev))
+       if (rtnl_port_fill(skb, dev, ext_filter_mask))
                goto nla_put_failure;
 
        if (dev->rtnl_link_ops || rtnl_have_link_slave_info(dev)) {
@@ -1198,6 +1233,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
        struct hlist_head *head;
        struct nlattr *tb[IFLA_MAX+1];
        u32 ext_filter_mask = 0;
+       int err;
 
        s_h = cb->args[0];
        s_idx = cb->args[1];
@@ -1218,11 +1254,17 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
                hlist_for_each_entry_rcu(dev, head, index_hlist) {
                        if (idx < s_idx)
                                goto cont;
-                       if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
-                                            NETLINK_CB(cb->skb).portid,
-                                            cb->nlh->nlmsg_seq, 0,
-                                            NLM_F_MULTI,
-                                            ext_filter_mask) <= 0)
+                       err = rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
+                                              NETLINK_CB(cb->skb).portid,
+                                              cb->nlh->nlmsg_seq, 0,
+                                              NLM_F_MULTI,
+                                              ext_filter_mask);
+                       /* If we ran out of room on the first message,
+                        * we're in trouble
+                        */
+                       WARN_ON((err == -EMSGSIZE) && (skb->len == 0));
+
+                       if (err <= 0)
                                goto out;
 
                        nl_dump_check_consistent(cb, nlmsg_hdr(skb));
@@ -1395,7 +1437,8 @@ static int do_set_master(struct net_device *dev, int ifindex)
        return 0;
 }
 
-static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
+static int do_setlink(const struct sk_buff *skb,
+                     struct net_device *dev, struct ifinfomsg *ifm,
                      struct nlattr **tb, char *ifname, int modified)
 {
        const struct net_device_ops *ops = dev->netdev_ops;
@@ -1407,7 +1450,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
                        err = PTR_ERR(net);
                        goto errout;
                }
-               if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) {
+               if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
                        err = -EPERM;
                        goto errout;
                }
@@ -1661,7 +1704,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh)
        if (err < 0)
                goto errout;
 
-       err = do_setlink(dev, ifm, tb, ifname, 0);
+       err = do_setlink(skb, dev, ifm, tb, ifname, 0);
 errout:
        return err;
 }
@@ -1778,7 +1821,8 @@ err:
 }
 EXPORT_SYMBOL(rtnl_create_link);
 
-static int rtnl_group_changelink(struct net *net, int group,
+static int rtnl_group_changelink(const struct sk_buff *skb,
+               struct net *net, int group,
                struct ifinfomsg *ifm,
                struct nlattr **tb)
 {
@@ -1787,7 +1831,7 @@ static int rtnl_group_changelink(struct net *net, int group,
 
        for_each_netdev(net, dev) {
                if (dev->group == group) {
-                       err = do_setlink(dev, ifm, tb, NULL, 0);
+                       err = do_setlink(skb, dev, ifm, tb, NULL, 0);
                        if (err < 0)
                                return err;
                }
@@ -1929,12 +1973,12 @@ replay:
                                modified = 1;
                        }
 
-                       return do_setlink(dev, ifm, tb, ifname, modified);
+                       return do_setlink(skb, dev, ifm, tb, ifname, modified);
                }
 
                if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
                        if (ifm->ifi_index == 0 && tb[IFLA_GROUP])
-                               return rtnl_group_changelink(net,
+                               return rtnl_group_changelink(skb, net,
                                                nla_get_u32(tb[IFLA_GROUP]),
                                                ifm, tb);
                        return -ENODEV;
@@ -2321,7 +2365,7 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh)
        int err = -EINVAL;
        __u8 *addr;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
        err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
@@ -2773,7 +2817,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        sz_idx = type>>2;
        kind = type&3;
 
-       if (kind != 2 && !ns_capable(net->user_ns, CAP_NET_ADMIN))
+       if (kind != 2 && !netlink_net_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
        if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
index 1b62343f58378b3d8fc0e3ea048dbb45ce1e3a76..8383b2bddeb923bd629da7d9eac2cdd1ff1d81bd 100644 (file)
@@ -3076,7 +3076,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
        if (unlikely(p->len + len >= 65536))
                return -E2BIG;
 
-       lp = NAPI_GRO_CB(p)->last ?: p;
+       lp = NAPI_GRO_CB(p)->last;
        pinfo = skb_shinfo(lp);
 
        if (headlen <= offset) {
@@ -3192,7 +3192,7 @@ merge:
 
        __skb_pull(skb, offset);
 
-       if (!NAPI_GRO_CB(p)->last)
+       if (NAPI_GRO_CB(p)->last == p)
                skb_shinfo(p)->frag_list = skb;
        else
                NAPI_GRO_CB(p)->last->next = skb;
index b4fff008136fafcca363e3a41ef441c2a1be878b..664ee4295b6f6ec38fb4f89d11c52eaa383a15d1 100644 (file)
 static DEFINE_MUTEX(proto_list_mutex);
 static LIST_HEAD(proto_list);
 
+/**
+ * sk_ns_capable - General socket capability test
+ * @sk: Socket to use a capability on or through
+ * @user_ns: The user namespace of the capability to use
+ * @cap: The capability to use
+ *
+ * Test to see if the opener of the socket had when the socket was
+ * created and the current process has the capability @cap in the user
+ * namespace @user_ns.
+ */
+bool sk_ns_capable(const struct sock *sk,
+                  struct user_namespace *user_ns, int cap)
+{
+       return file_ns_capable(sk->sk_socket->file, user_ns, cap) &&
+               ns_capable(user_ns, cap);
+}
+EXPORT_SYMBOL(sk_ns_capable);
+
+/**
+ * sk_capable - Socket global capability test
+ * @sk: Socket to use a capability on or through
+ * @cap: The global capbility to use
+ *
+ * Test to see if the opener of the socket had when the socket was
+ * created and the current process has the capability @cap in all user
+ * namespaces.
+ */
+bool sk_capable(const struct sock *sk, int cap)
+{
+       return sk_ns_capable(sk, &init_user_ns, cap);
+}
+EXPORT_SYMBOL(sk_capable);
+
+/**
+ * sk_net_capable - Network namespace socket capability test
+ * @sk: Socket to use a capability on or through
+ * @cap: The capability to use
+ *
+ * Test to see if the opener of the socket had when the socke was created
+ * and the current process has the capability @cap over the network namespace
+ * the socket is a member of.
+ */
+bool sk_net_capable(const struct sock *sk, int cap)
+{
+       return sk_ns_capable(sk, sock_net(sk)->user_ns, cap);
+}
+EXPORT_SYMBOL(sk_net_capable);
+
+
 #ifdef CONFIG_MEMCG_KMEM
 int mem_cgroup_sockets_init(struct mem_cgroup *memcg, struct cgroup_subsys *ss)
 {
index d7af1885932269eb9f4196fe1211a6d09e298b97..a4216a4c95720f105b0cd7841cd59e84d3dda7a6 100644 (file)
@@ -49,7 +49,7 @@ int sock_diag_put_meminfo(struct sock *sk, struct sk_buff *skb, int attrtype)
 }
 EXPORT_SYMBOL_GPL(sock_diag_put_meminfo);
 
-int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk,
+int sock_diag_put_filterinfo(bool may_report_filterinfo, struct sock *sk,
                             struct sk_buff *skb, int attrtype)
 {
        struct sock_fprog_kern *fprog;
@@ -58,7 +58,7 @@ int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk,
        unsigned int flen;
        int err = 0;
 
-       if (!ns_capable(user_ns, CAP_NET_ADMIN)) {
+       if (!may_report_filterinfo) {
                nla_reserve(skb, attrtype, 0);
                return 0;
        }
index 2f737bf90b3fe4235c75ccca6640c735ecaa076b..eed34338736c275aa02bfa40448801d46dda736b 100644 (file)
@@ -348,8 +348,8 @@ static void __net_random_once_deferred(struct work_struct *w)
 {
        struct __net_random_once_work *work =
                container_of(w, struct __net_random_once_work, work);
-       if (!static_key_enabled(work->key))
-               static_key_slow_inc(work->key);
+       BUG_ON(!static_key_enabled(work->key));
+       static_key_slow_dec(work->key);
        kfree(work);
 }
 
@@ -367,7 +367,7 @@ static void __net_random_once_disable_jump(struct static_key *key)
 }
 
 bool __net_get_random_once(void *buf, int nbytes, bool *done,
-                          struct static_key *done_key)
+                          struct static_key *once_key)
 {
        static DEFINE_SPINLOCK(lock);
        unsigned long flags;
@@ -382,7 +382,7 @@ bool __net_get_random_once(void *buf, int nbytes, bool *done,
        *done = true;
        spin_unlock_irqrestore(&lock, flags);
 
-       __net_random_once_disable_jump(done_key);
+       __net_random_once_disable_jump(once_key);
 
        return true;
 }
index 553644402670b3461bde7fb26705ddde8729be75..f8b98d89c28527f049b4c3132aa7f0b412cfa0ef 100644 (file)
@@ -1669,7 +1669,7 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh)
        struct nlmsghdr *reply_nlh = NULL;
        const struct reply_func *fn;
 
-       if ((nlh->nlmsg_type == RTM_SETDCB) && !capable(CAP_NET_ADMIN))
+       if ((nlh->nlmsg_type == RTM_SETDCB) && !netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
        ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX,
index a603823a3e279c850d1641e5f4d59be983400488..3b726f31c64c0b88efcfacd4d64df7177260ad5c 100644 (file)
@@ -574,7 +574,7 @@ static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh)
        struct dn_ifaddr __rcu **ifap;
        int err = -EINVAL;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
        if (!net_eq(net, &init_net))
@@ -618,7 +618,7 @@ static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
        struct dn_ifaddr *ifa;
        int err;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
        if (!net_eq(net, &init_net))
index 57dc159245ecfff38e318626cf0ea1ffa9db1cae..d332aefb0846f86a11d924e3e1e7ad23e279dda2 100644 (file)
@@ -505,7 +505,7 @@ static int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh)
        struct nlattr *attrs[RTA_MAX+1];
        int err;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
        if (!net_eq(net, &init_net))
@@ -530,7 +530,7 @@ static int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh)
        struct nlattr *attrs[RTA_MAX+1];
        int err;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
        if (!net_eq(net, &init_net))
index e83015cecfa7507d551bd19e4b4121ad0f25eeaf..e4d9560a910b0eb96ed3a4ad59d63771f865de3c 100644 (file)
@@ -107,7 +107,7 @@ static inline void dnrmg_receive_user_skb(struct sk_buff *skb)
        if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
                return;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!netlink_capable(skb, CAP_NET_ADMIN))
                RCV_SKB_FAIL(-EPERM);
 
        /* Eventually we might send routing messages too */
index 0eb5d5e76dfbe1f99537e8a561f1671389c09e16..5db37cef50a9ccd80c642118f54dd4ecf04219b8 100644 (file)
@@ -406,8 +406,9 @@ static int dsa_of_probe(struct platform_device *pdev)
                goto out_free;
        }
 
-       chip_index = 0;
+       chip_index = -1;
        for_each_available_child_of_node(np, child) {
+               chip_index++;
                cd = &pd->chip[chip_index];
 
                cd->mii_bus = &mdio_bus->dev;
index 8c54870db792cab059bff464d29776510ec3e5ec..6d6dd345bc4d89dea7dac7b179e4ef0f391b3954 100644 (file)
@@ -1650,6 +1650,39 @@ static int __init init_ipv4_mibs(void)
        return register_pernet_subsys(&ipv4_mib_ops);
 }
 
+static __net_init int inet_init_net(struct net *net)
+{
+       /*
+        * Set defaults for local port range
+        */
+       seqlock_init(&net->ipv4.ip_local_ports.lock);
+       net->ipv4.ip_local_ports.range[0] =  32768;
+       net->ipv4.ip_local_ports.range[1] =  61000;
+
+       seqlock_init(&net->ipv4.ping_group_range.lock);
+       /*
+        * Sane defaults - nobody may create ping sockets.
+        * Boot scripts should set this to distro-specific group.
+        */
+       net->ipv4.ping_group_range.range[0] = make_kgid(&init_user_ns, 1);
+       net->ipv4.ping_group_range.range[1] = make_kgid(&init_user_ns, 0);
+       return 0;
+}
+
+static __net_exit void inet_exit_net(struct net *net)
+{
+}
+
+static __net_initdata struct pernet_operations af_inet_ops = {
+       .init = inet_init_net,
+       .exit = inet_exit_net,
+};
+
+static int __init init_inet_pernet_ops(void)
+{
+       return register_pernet_subsys(&af_inet_ops);
+}
+
 static int ipv4_proc_init(void);
 
 /*
@@ -1794,6 +1827,9 @@ static int __init inet_init(void)
        if (ip_mr_init())
                pr_crit("%s: Cannot init ipv4 mroute\n", __func__);
 #endif
+
+       if (init_inet_pernet_ops())
+               pr_crit("%s: Cannot init ipv4 inet pernet ops\n", __func__);
        /*
         *      Initialise per-cpu ipv4 mibs
         */
index 8a043f03c88ecbb418b5466953abefd54c50b1d0..b10cd43a4722730205272d7822d699bc49ea71d3 100644 (file)
@@ -821,13 +821,13 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
        fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
        if (fi == NULL)
                goto failure;
+       fib_info_cnt++;
        if (cfg->fc_mx) {
                fi->fib_metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL);
                if (!fi->fib_metrics)
                        goto failure;
        } else
                fi->fib_metrics = (u32 *) dst_default_metrics;
-       fib_info_cnt++;
 
        fi->fib_net = hold_net(net);
        fi->fib_protocol = cfg->fc_protocol;
index 0d1e2cb877ec43692c5a7b4fe57e16cf921a8c97..a56b8e6e866a8c4327f86111adac947e9ffc2445 100644 (file)
@@ -37,11 +37,11 @@ void inet_get_local_port_range(struct net *net, int *low, int *high)
        unsigned int seq;
 
        do {
-               seq = read_seqbegin(&net->ipv4.sysctl_local_ports.lock);
+               seq = read_seqbegin(&net->ipv4.ip_local_ports.lock);
 
-               *low = net->ipv4.sysctl_local_ports.range[0];
-               *high = net->ipv4.sysctl_local_ports.range[1];
-       } while (read_seqretry(&net->ipv4.sysctl_local_ports.lock, seq));
+               *low = net->ipv4.ip_local_ports.range[0];
+               *high = net->ipv4.ip_local_ports.range[1];
+       } while (read_seqretry(&net->ipv4.ip_local_ports.lock, seq));
 }
 EXPORT_SYMBOL(inet_get_local_port_range);
 
index be8abe73bb9f464a2e68679255acde3b708ce84b..6f111e48e11c15a19ffd60d345b1399fd3c66953 100644 (file)
 static bool ip_may_fragment(const struct sk_buff *skb)
 {
        return unlikely((ip_hdr(skb)->frag_off & htons(IP_DF)) == 0) ||
-              !skb->local_df;
+               skb->local_df;
 }
 
 static bool ip_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)
 {
-       if (skb->len <= mtu || skb->local_df)
+       if (skb->len <= mtu)
                return false;
 
        if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu)
@@ -56,53 +56,6 @@ static bool ip_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)
        return true;
 }
 
-static bool ip_gso_exceeds_dst_mtu(const struct sk_buff *skb)
-{
-       unsigned int mtu;
-
-       if (skb->local_df || !skb_is_gso(skb))
-               return false;
-
-       mtu = ip_dst_mtu_maybe_forward(skb_dst(skb), true);
-
-       /* if seglen > mtu, do software segmentation for IP fragmentation on
-        * output.  DF bit cannot be set since ip_forward would have sent
-        * icmp error.
-        */
-       return skb_gso_network_seglen(skb) > mtu;
-}
-
-/* called if GSO skb needs to be fragmented on forward */
-static int ip_forward_finish_gso(struct sk_buff *skb)
-{
-       struct dst_entry *dst = skb_dst(skb);
-       netdev_features_t features;
-       struct sk_buff *segs;
-       int ret = 0;
-
-       features = netif_skb_dev_features(skb, dst->dev);
-       segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
-       if (IS_ERR(segs)) {
-               kfree_skb(skb);
-               return -ENOMEM;
-       }
-
-       consume_skb(skb);
-
-       do {
-               struct sk_buff *nskb = segs->next;
-               int err;
-
-               segs->next = NULL;
-               err = dst_output(segs);
-
-               if (err && ret == 0)
-                       ret = err;
-               segs = nskb;
-       } while (segs);
-
-       return ret;
-}
 
 static int ip_forward_finish(struct sk_buff *skb)
 {
@@ -114,9 +67,6 @@ static int ip_forward_finish(struct sk_buff *skb)
        if (unlikely(opt->optlen))
                ip_forward_options(skb);
 
-       if (ip_gso_exceeds_dst_mtu(skb))
-               return ip_forward_finish_gso(skb);
-
        return dst_output(skb);
 }
 
index c10a3ce5cbff0fc0bd0f23ac72188fd9e39fa83f..ed32313e307c43202a4710c6f5b74e14c19a4c20 100644 (file)
@@ -232,8 +232,9 @@ static void ip_expire(unsigned long arg)
                 * "Fragment Reassembly Timeout" message, per RFC792.
                 */
                if (qp->user == IP_DEFRAG_AF_PACKET ||
-                   (qp->user == IP_DEFRAG_CONNTRACK_IN &&
-                    skb_rtable(head)->rt_type != RTN_LOCAL))
+                   ((qp->user >= IP_DEFRAG_CONNTRACK_IN) &&
+                    (qp->user <= __IP_DEFRAG_CONNTRACK_IN_END) &&
+                    (skb_rtable(head)->rt_type != RTN_LOCAL)))
                        goto out_rcu_unlock;
 
 
index 1cbeba5edff90fa1ac891d4dd23cfb65464878a4..a52f50187b5495a1157c2ef8e0785da730414022 100644 (file)
@@ -211,6 +211,48 @@ static inline int ip_finish_output2(struct sk_buff *skb)
        return -EINVAL;
 }
 
+static int ip_finish_output_gso(struct sk_buff *skb)
+{
+       netdev_features_t features;
+       struct sk_buff *segs;
+       int ret = 0;
+
+       /* common case: locally created skb or seglen is <= mtu */
+       if (((IPCB(skb)->flags & IPSKB_FORWARDED) == 0) ||
+             skb_gso_network_seglen(skb) <= ip_skb_dst_mtu(skb))
+               return ip_finish_output2(skb);
+
+       /* Slowpath -  GSO segment length is exceeding the dst MTU.
+        *
+        * This can happen in two cases:
+        * 1) TCP GRO packet, DF bit not set
+        * 2) skb arrived via virtio-net, we thus get TSO/GSO skbs directly
+        * from host network stack.
+        */
+       features = netif_skb_features(skb);
+       segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
+       if (IS_ERR(segs)) {
+               kfree_skb(skb);
+               return -ENOMEM;
+       }
+
+       consume_skb(skb);
+
+       do {
+               struct sk_buff *nskb = segs->next;
+               int err;
+
+               segs->next = NULL;
+               err = ip_fragment(segs, ip_finish_output2);
+
+               if (err && ret == 0)
+                       ret = err;
+               segs = nskb;
+       } while (segs);
+
+       return ret;
+}
+
 static int ip_finish_output(struct sk_buff *skb)
 {
 #if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)
@@ -220,10 +262,13 @@ static int ip_finish_output(struct sk_buff *skb)
                return dst_output(skb);
        }
 #endif
-       if (skb->len > ip_skb_dst_mtu(skb) && !skb_is_gso(skb))
+       if (skb_is_gso(skb))
+               return ip_finish_output_gso(skb);
+
+       if (skb->len > ip_skb_dst_mtu(skb))
                return ip_fragment(skb, ip_finish_output2);
-       else
-               return ip_finish_output2(skb);
+
+       return ip_finish_output2(skb);
 }
 
 int ip_mc_output(struct sock *sk, struct sk_buff *skb)
index fa5b7519765f10c61b8855c6646b79915384062f..2acc2337d38bfe7f35517e13952cfa8a306c24fd 100644 (file)
@@ -442,6 +442,8 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
                tunnel->i_seqno = ntohl(tpi->seq) + 1;
        }
 
+       skb_reset_network_header(skb);
+
        err = IP_ECN_decapsulate(iph, skb);
        if (unlikely(err)) {
                if (log_ecn_error)
@@ -538,9 +540,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        unsigned int max_headroom;      /* The extra header space needed */
        __be32 dst;
        int err;
-       bool connected = true;
+       bool connected;
 
        inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
+       connected = (tunnel->parms.iph.daddr != 0);
 
        dst = tnl_params->daddr;
        if (dst == 0) {
@@ -880,6 +883,7 @@ int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
         */
        if (!IS_ERR(itn->fb_tunnel_dev)) {
                itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL;
+               itn->fb_tunnel_dev->mtu = ip_tunnel_bind_dev(itn->fb_tunnel_dev);
                ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev));
        }
        rtnl_unlock();
index afcee51b90ede30a846bbd7a5c16b6996d955889..13ef00f1e17b88943ddee9ae9ba52b7d0efe7832 100644 (file)
@@ -239,6 +239,7 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 static int vti4_err(struct sk_buff *skb, u32 info)
 {
        __be32 spi;
+       __u32 mark;
        struct xfrm_state *x;
        struct ip_tunnel *tunnel;
        struct ip_esp_hdr *esph;
@@ -254,6 +255,8 @@ static int vti4_err(struct sk_buff *skb, u32 info)
        if (!tunnel)
                return -1;
 
+       mark = be32_to_cpu(tunnel->parms.o_key);
+
        switch (protocol) {
        case IPPROTO_ESP:
                esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2));
@@ -281,7 +284,7 @@ static int vti4_err(struct sk_buff *skb, u32 info)
                return 0;
        }
 
-       x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
+       x = xfrm_state_lookup(net, mark, (const xfrm_address_t *)&iph->daddr,
                              spi, protocol, AF_INET);
        if (!x)
                return 0;
index 12e13bd82b5bba4fdd183d5ba2cda098a1c0c683..f40f321b41fc2e30b21019333efdc5757404fe0a 100644 (file)
@@ -22,7 +22,6 @@
 #endif
 #include <net/netfilter/nf_conntrack_zones.h>
 
-/* Returns new sk_buff, or NULL */
 static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
 {
        int err;
@@ -33,8 +32,10 @@ static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
        err = ip_defrag(skb, user);
        local_bh_enable();
 
-       if (!err)
+       if (!err) {
                ip_send_check(ip_hdr(skb));
+               skb->local_df = 1;
+       }
 
        return err;
 }
index 8210964a9f19bedf17d6f3266c1fd0775f3de144..044a0ddf6a791ace04fbb1802e64563bf3fc5518 100644 (file)
@@ -236,15 +236,15 @@ exit:
 static void inet_get_ping_group_range_net(struct net *net, kgid_t *low,
                                          kgid_t *high)
 {
-       kgid_t *data = net->ipv4.sysctl_ping_group_range;
+       kgid_t *data = net->ipv4.ping_group_range.range;
        unsigned int seq;
 
        do {
-               seq = read_seqbegin(&net->ipv4.sysctl_local_ports.lock);
+               seq = read_seqbegin(&net->ipv4.ping_group_range.lock);
 
                *low = data[0];
                *high = data[1];
-       } while (read_seqretry(&net->ipv4.sysctl_local_ports.lock, seq));
+       } while (read_seqretry(&net->ipv4.ping_group_range.lock, seq));
 }
 
 
index db1e0da871f40a2284d67bd48c0f21d772b923f3..5e676be3daeb19e5f48df5e767a66b83ac73b432 100644 (file)
@@ -1519,7 +1519,7 @@ static int __mkroute_input(struct sk_buff *skb,
        struct in_device *out_dev;
        unsigned int flags = 0;
        bool do_cache;
-       u32 itag;
+       u32 itag = 0;
 
        /* get a working reference to the output device */
        out_dev = __in_dev_get_rcu(FIB_RES_DEV(*res));
index 44eba052b43d3ab49ba7630bcd82e73e5b094472..5cde8f263d40c0eb0204d310fee99146dabb7a87 100644 (file)
@@ -45,10 +45,10 @@ static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX };
 /* Update system visible IP port range */
 static void set_local_port_range(struct net *net, int range[2])
 {
-       write_seqlock(&net->ipv4.sysctl_local_ports.lock);
-       net->ipv4.sysctl_local_ports.range[0] = range[0];
-       net->ipv4.sysctl_local_ports.range[1] = range[1];
-       write_sequnlock(&net->ipv4.sysctl_local_ports.lock);
+       write_seqlock(&net->ipv4.ip_local_ports.lock);
+       net->ipv4.ip_local_ports.range[0] = range[0];
+       net->ipv4.ip_local_ports.range[1] = range[1];
+       write_sequnlock(&net->ipv4.ip_local_ports.lock);
 }
 
 /* Validate changes from /proc interface. */
@@ -57,7 +57,7 @@ static int ipv4_local_port_range(struct ctl_table *table, int write,
                                 size_t *lenp, loff_t *ppos)
 {
        struct net *net =
-               container_of(table->data, struct net, ipv4.sysctl_local_ports.range);
+               container_of(table->data, struct net, ipv4.ip_local_ports.range);
        int ret;
        int range[2];
        struct ctl_table tmp = {
@@ -87,14 +87,14 @@ static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low
 {
        kgid_t *data = table->data;
        struct net *net =
-               container_of(table->data, struct net, ipv4.sysctl_ping_group_range);
+               container_of(table->data, struct net, ipv4.ping_group_range.range);
        unsigned int seq;
        do {
-               seq = read_seqbegin(&net->ipv4.sysctl_local_ports.lock);
+               seq = read_seqbegin(&net->ipv4.ip_local_ports.lock);
 
                *low = data[0];
                *high = data[1];
-       } while (read_seqretry(&net->ipv4.sysctl_local_ports.lock, seq));
+       } while (read_seqretry(&net->ipv4.ip_local_ports.lock, seq));
 }
 
 /* Update system visible IP port range */
@@ -102,11 +102,11 @@ static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t hig
 {
        kgid_t *data = table->data;
        struct net *net =
-               container_of(table->data, struct net, ipv4.sysctl_ping_group_range);
-       write_seqlock(&net->ipv4.sysctl_local_ports.lock);
+               container_of(table->data, struct net, ipv4.ping_group_range.range);
+       write_seqlock(&net->ipv4.ip_local_ports.lock);
        data[0] = low;
        data[1] = high;
-       write_sequnlock(&net->ipv4.sysctl_local_ports.lock);
+       write_sequnlock(&net->ipv4.ip_local_ports.lock);
 }
 
 /* Validate changes from /proc interface. */
@@ -805,7 +805,7 @@ static struct ctl_table ipv4_net_table[] = {
        },
        {
                .procname       = "ping_group_range",
-               .data           = &init_net.ipv4.sysctl_ping_group_range,
+               .data           = &init_net.ipv4.ping_group_range.range,
                .maxlen         = sizeof(gid_t)*2,
                .mode           = 0644,
                .proc_handler   = ipv4_ping_group_range,
@@ -819,8 +819,8 @@ static struct ctl_table ipv4_net_table[] = {
        },
        {
                .procname       = "ip_local_port_range",
-               .maxlen         = sizeof(init_net.ipv4.sysctl_local_ports.range),
-               .data           = &init_net.ipv4.sysctl_local_ports.range,
+               .maxlen         = sizeof(init_net.ipv4.ip_local_ports.range),
+               .data           = &init_net.ipv4.ip_local_ports.range,
                .mode           = 0644,
                .proc_handler   = ipv4_local_port_range,
        },
@@ -858,20 +858,6 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
                        table[i].data += (void *)net - (void *)&init_net;
        }
 
-       /*
-        * Sane defaults - nobody may create ping sockets.
-        * Boot scripts should set this to distro-specific group.
-        */
-       net->ipv4.sysctl_ping_group_range[0] = make_kgid(&init_user_ns, 1);
-       net->ipv4.sysctl_ping_group_range[1] = make_kgid(&init_user_ns, 0);
-
-       /*
-        * Set defaults for local port range
-        */
-       seqlock_init(&net->ipv4.sysctl_local_ports.lock);
-       net->ipv4.sysctl_local_ports.range[0] =  32768;
-       net->ipv4.sysctl_local_ports.range[1] =  61000;
-
        net->ipv4.ipv4_hdr = register_net_sysctl(net, "net/ipv4", table);
        if (net->ipv4.ipv4_hdr == NULL)
                goto err_reg;
index 8bf224516ba2a26a661d16f89aaee32301d09397..b4f1b29b08bdf14acfc6153cd443c9e799eeb141 100644 (file)
@@ -409,7 +409,7 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us)
                ratio -= ca->delayed_ack >> ACK_RATIO_SHIFT;
                ratio += cnt;
 
-               ca->delayed_ack = min(ratio, ACK_RATIO_LIMIT);
+               ca->delayed_ack = clamp(ratio, 1U, ACK_RATIO_LIMIT);
        }
 
        /* Some calls are for duplicates without timetamps */
index 025e25093984bacaca7a5cdaa26074d436f29cf1..12d6016bdd9a675aa39fb24fd91fb8c80c741ed3 100644 (file)
@@ -2441,8 +2441,14 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
                err = tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
        }
 
-       if (likely(!err))
+       if (likely(!err)) {
                TCP_SKB_CB(skb)->sacked |= TCPCB_EVER_RETRANS;
+               /* Update global TCP statistics. */
+               TCP_INC_STATS(sock_net(sk), TCP_MIB_RETRANSSEGS);
+               if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)
+                       NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNRETRANS);
+               tp->total_retrans++;
+       }
        return err;
 }
 
@@ -2452,12 +2458,6 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
        int err = __tcp_retransmit_skb(sk, skb);
 
        if (err == 0) {
-               /* Update global TCP statistics. */
-               TCP_INC_STATS(sock_net(sk), TCP_MIB_RETRANSSEGS);
-               if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)
-                       NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNRETRANS);
-               tp->total_retrans++;
-
 #if FASTRETRANS_DEBUG > 0
                if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS) {
                        net_dbg_ratelimited("retrans_out leaked\n");
index 40e701f2e1e0324af6f0af781ac6715866ad88d3..186a8ecf92fa84bda9d0f6b050131da603c7694a 100644 (file)
@@ -62,10 +62,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
        if (err)
                return err;
 
-       memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
-       IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED;
-
-       skb->protocol = htons(ETH_P_IP);
+       IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
 
        return x->outer_mode->output2(x, skb);
 }
@@ -73,27 +70,34 @@ EXPORT_SYMBOL(xfrm4_prepare_output);
 
 int xfrm4_output_finish(struct sk_buff *skb)
 {
+       memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+       skb->protocol = htons(ETH_P_IP);
+
+#ifdef CONFIG_NETFILTER
+       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
+#endif
+
+       return xfrm_output(skb);
+}
+
+static int __xfrm4_output(struct sk_buff *skb)
+{
+       struct xfrm_state *x = skb_dst(skb)->xfrm;
+
 #ifdef CONFIG_NETFILTER
-       if (!skb_dst(skb)->xfrm) {
+       if (!x) {
                IPCB(skb)->flags |= IPSKB_REROUTED;
                return dst_output(skb);
        }
-
-       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
 #endif
 
-       skb->protocol = htons(ETH_P_IP);
-       return xfrm_output(skb);
+       return x->outer_mode->afinfo->output_finish(skb);
 }
 
 int xfrm4_output(struct sock *sk, struct sk_buff *skb)
 {
-       struct dst_entry *dst = skb_dst(skb);
-       struct xfrm_state *x = dst->xfrm;
-
        return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb,
-                           NULL, dst->dev,
-                           x->outer_mode->afinfo->output_finish,
+                           NULL, skb_dst(skb)->dev, __xfrm4_output,
                            !(IPCB(skb)->flags & IPSKB_REROUTED));
 }
 
index 7f7b243e8139defccf14165971a92a7261c29b71..a2ce0101eaac846b1e36e69a5a89c804ca247c44 100644 (file)
@@ -50,8 +50,12 @@ int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
 {
        int ret;
        struct xfrm4_protocol *handler;
+       struct xfrm4_protocol __rcu **head = proto_handlers(protocol);
 
-       for_each_protocol_rcu(*proto_handlers(protocol), handler)
+       if (!head)
+               return 0;
+
+       for_each_protocol_rcu(*head, handler)
                if ((ret = handler->cb_handler(skb, err)) <= 0)
                        return ret;
 
@@ -64,15 +68,20 @@ int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
 {
        int ret;
        struct xfrm4_protocol *handler;
+       struct xfrm4_protocol __rcu **head = proto_handlers(nexthdr);
 
        XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
        XFRM_SPI_SKB_CB(skb)->family = AF_INET;
        XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
 
-       for_each_protocol_rcu(*proto_handlers(nexthdr), handler)
+       if (!head)
+               goto out;
+
+       for_each_protocol_rcu(*head, handler)
                if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL)
                        return ret;
 
+out:
        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
 
        kfree_skb(skb);
@@ -208,6 +217,9 @@ int xfrm4_protocol_register(struct xfrm4_protocol *handler,
        int ret = -EEXIST;
        int priority = handler->priority;
 
+       if (!proto_handlers(protocol) || !netproto(protocol))
+               return -EINVAL;
+
        mutex_lock(&xfrm4_protocol_mutex);
 
        if (!rcu_dereference_protected(*proto_handlers(protocol),
@@ -250,6 +262,9 @@ int xfrm4_protocol_deregister(struct xfrm4_protocol *handler,
        struct xfrm4_protocol *t;
        int ret = -ENOENT;
 
+       if (!proto_handlers(protocol) || !netproto(protocol))
+               return -EINVAL;
+
        mutex_lock(&xfrm4_protocol_mutex);
 
        for (pprev = proto_handlers(protocol);
index 34e0ded5c14b028ebbb1bb03c1b30e8f25f98811..87891f5f57b5786725321d2fc301941531064bf2 100644 (file)
@@ -1459,7 +1459,7 @@ static int fib6_walk_continue(struct fib6_walker_t *w)
 
                                if (w->skip) {
                                        w->skip--;
-                                       continue;
+                                       goto skip;
                                }
 
                                err = w->func(w);
@@ -1469,6 +1469,7 @@ static int fib6_walk_continue(struct fib6_walker_t *w)
                                w->count++;
                                continue;
                        }
+skip:
                        w->state = FWS_U;
                case FWS_U:
                        if (fn == w->root)
index 59f95affceb0773d052184bdf5fec9f276433d63..b2f091566f88453bce5eb3c33b47e1c9c040447c 100644 (file)
@@ -196,7 +196,6 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
        unsigned int off;
        u16 flush = 1;
        int proto;
-       __wsum csum;
 
        off = skb_gro_offset(skb);
        hlen = off + sizeof(*iph);
@@ -264,13 +263,10 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
 
        NAPI_GRO_CB(skb)->flush |= flush;
 
-       csum = skb->csum;
-       skb_postpull_rcsum(skb, iph, skb_network_header_len(skb));
+       skb_gro_postpull_rcsum(skb, iph, nlen);
 
        pp = ops->callbacks.gro_receive(head, skb);
 
-       skb->csum = csum;
-
 out_unlock:
        rcu_read_unlock();
 
index 40e7581374f7006c6f8c436ed686919ac93c2b19..fbf11562b54c1a7c8809f33cc969c66319517377 100644 (file)
@@ -344,12 +344,16 @@ static unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst)
 
 static bool ip6_pkt_too_big(const struct sk_buff *skb, unsigned int mtu)
 {
-       if (skb->len <= mtu || skb->local_df)
+       if (skb->len <= mtu)
                return false;
 
+       /* ipv6 conntrack defrag sets max_frag_size + local_df */
        if (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu)
                return true;
 
+       if (skb->local_df)
+               return false;
+
        if (skb_is_gso(skb) && skb_gso_network_seglen(skb) <= mtu)
                return false;
 
@@ -1225,7 +1229,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
                unsigned int maxnonfragsize, headersize;
 
                headersize = sizeof(struct ipv6hdr) +
-                            (opt ? opt->tot_len : 0) +
+                            (opt ? opt->opt_flen + opt->opt_nflen : 0) +
                             (dst_allfrag(&rt->dst) ?
                              sizeof(struct frag_hdr) : 0) +
                             rt->rt6i_nfheader_len;
index b05b609f69d1cd3e58bd525cb0b5e8b11d429b80..f6a66bb4114db3af0f23ee1f950acf8b9720304d 100644 (file)
@@ -1557,7 +1557,7 @@ static int ip6_tnl_validate(struct nlattr *tb[], struct nlattr *data[])
 {
        u8 proto;
 
-       if (!data)
+       if (!data || !data[IFLA_IPTUN_PROTO])
                return 0;
 
        proto = nla_get_u8(data[IFLA_IPTUN_PROTO]);
index b7c0f827140b402685cc29049cb56646471c2cf2..6cc9f9371cc57cd6b0233815a73134dddfa6207c 100644 (file)
@@ -511,6 +511,7 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                    u8 type, u8 code, int offset, __be32 info)
 {
        __be32 spi;
+       __u32 mark;
        struct xfrm_state *x;
        struct ip6_tnl *t;
        struct ip_esp_hdr *esph;
@@ -524,6 +525,8 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        if (!t)
                return -1;
 
+       mark = be32_to_cpu(t->parms.o_key);
+
        switch (protocol) {
        case IPPROTO_ESP:
                esph = (struct ip_esp_hdr *)(skb->data + offset);
@@ -545,7 +548,7 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
            type != NDISC_REDIRECT)
                return 0;
 
-       x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr,
+       x = xfrm_state_lookup(net, mark, (const xfrm_address_t *)&iph->daddr,
                              spi, protocol, AF_INET6);
        if (!x)
                return 0;
@@ -1097,7 +1100,6 @@ static int __init vti6_tunnel_init(void)
 
        err = xfrm6_protocol_register(&vti_esp6_protocol, IPPROTO_ESP);
        if (err < 0) {
-               unregister_pernet_device(&vti6_net_ops);
                pr_err("%s: can't register vti6 protocol\n", __func__);
 
                goto out;
@@ -1106,7 +1108,6 @@ static int __init vti6_tunnel_init(void)
        err = xfrm6_protocol_register(&vti_ah6_protocol, IPPROTO_AH);
        if (err < 0) {
                xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP);
-               unregister_pernet_device(&vti6_net_ops);
                pr_err("%s: can't register vti6 protocol\n", __func__);
 
                goto out;
@@ -1116,7 +1117,6 @@ static int __init vti6_tunnel_init(void)
        if (err < 0) {
                xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH);
                xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP);
-               unregister_pernet_device(&vti6_net_ops);
                pr_err("%s: can't register vti6 protocol\n", __func__);
 
                goto out;
index 8659067da28e8a8557af6f4109fc52056ccdee1b..8250474ab7dc0e10b3340bca3e68aaf9377a81f2 100644 (file)
@@ -1633,7 +1633,7 @@ struct sock *mroute6_socket(struct net *net, struct sk_buff *skb)
 {
        struct mr6_table *mrt;
        struct flowi6 fl6 = {
-               .flowi6_iif     = skb->skb_iif,
+               .flowi6_iif     = skb->skb_iif ? : LOOPBACK_IFINDEX,
                .flowi6_oif     = skb->dev->ifindex,
                .flowi6_mark    = skb->mark,
        };
index 09a22f4f36c9e069c6dfb3074909691ef2c82399..ca8d4ea48a5d9fa641bf129a6fc5e3b428799fa4 100644 (file)
@@ -851,7 +851,7 @@ out:
 static void ndisc_recv_na(struct sk_buff *skb)
 {
        struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb);
-       const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
+       struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
        const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
        u8 *lladdr = NULL;
        u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) +
@@ -944,10 +944,7 @@ static void ndisc_recv_na(struct sk_buff *skb)
                        /*
                         * Change: router to host
                         */
-                       struct rt6_info *rt;
-                       rt = rt6_get_dflt_router(saddr, dev);
-                       if (rt)
-                               ip6_del_rt(rt);
+                       rt6_clean_tohost(dev_net(dev),  saddr);
                }
 
 out:
index 95f3f1da0d7f2ff20c3afa3eeda315dd9e2e6b5f..d38e6a8d8b9fb82ec7d583a5ab2abc652838d470 100644 (file)
@@ -30,13 +30,15 @@ int ip6_route_me_harder(struct sk_buff *skb)
                .daddr = iph->daddr,
                .saddr = iph->saddr,
        };
+       int err;
 
        dst = ip6_route_output(net, skb->sk, &fl6);
-       if (dst->error) {
+       err = dst->error;
+       if (err) {
                IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
                LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n");
                dst_release(dst);
-               return dst->error;
+               return err;
        }
 
        /* Drop old route. */
index e0983f3648a628410c6f6bfd9549ec339a325353..790e0c6b19e1caa41b31c5f279de719581bd6065 100644 (file)
@@ -33,6 +33,7 @@ static bool rpfilter_lookup_reverse6(const struct sk_buff *skb,
        struct ipv6hdr *iph = ipv6_hdr(skb);
        bool ret = false;
        struct flowi6 fl6 = {
+               .flowi6_iif = LOOPBACK_IFINDEX,
                .flowlabel = (* (__be32 *) iph) & IPV6_FLOWINFO_MASK,
                .flowi6_proto = iph->nexthdr,
                .daddr = iph->saddr,
index 4011617cca688850c4d530f2e35d9890203dedaf..6ebdb7b6744cc933801dcf4c6b3dea6ddce8a89c 100644 (file)
@@ -1273,6 +1273,7 @@ void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark)
        struct flowi6 fl6;
 
        memset(&fl6, 0, sizeof(fl6));
+       fl6.flowi6_iif = LOOPBACK_IFINDEX;
        fl6.flowi6_oif = oif;
        fl6.flowi6_mark = mark;
        fl6.daddr = iph->daddr;
@@ -1294,6 +1295,7 @@ void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
        struct flowi6 fl6;
 
        memset(&fl6, 0, sizeof(fl6));
+       fl6.flowi6_iif = LOOPBACK_IFINDEX;
        fl6.flowi6_oif = oif;
        fl6.flowi6_mark = mark;
        fl6.daddr = msg->dest;
@@ -2232,6 +2234,27 @@ void rt6_remove_prefsrc(struct inet6_ifaddr *ifp)
        fib6_clean_all(net, fib6_remove_prefsrc, &adni);
 }
 
+#define RTF_RA_ROUTER          (RTF_ADDRCONF | RTF_DEFAULT | RTF_GATEWAY)
+#define RTF_CACHE_GATEWAY      (RTF_GATEWAY | RTF_CACHE)
+
+/* Remove routers and update dst entries when gateway turn into host. */
+static int fib6_clean_tohost(struct rt6_info *rt, void *arg)
+{
+       struct in6_addr *gateway = (struct in6_addr *)arg;
+
+       if ((((rt->rt6i_flags & RTF_RA_ROUTER) == RTF_RA_ROUTER) ||
+            ((rt->rt6i_flags & RTF_CACHE_GATEWAY) == RTF_CACHE_GATEWAY)) &&
+            ipv6_addr_equal(gateway, &rt->rt6i_gateway)) {
+               return -1;
+       }
+       return 0;
+}
+
+void rt6_clean_tohost(struct net *net, struct in6_addr *gateway)
+{
+       fib6_clean_all(net, fib6_clean_tohost, gateway);
+}
+
 struct arg_dev_net {
        struct net_device *dev;
        struct net *net;
@@ -2707,6 +2730,9 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh)
        if (tb[RTA_OIF])
                oif = nla_get_u32(tb[RTA_OIF]);
 
+       if (tb[RTA_MARK])
+               fl6.flowi6_mark = nla_get_u32(tb[RTA_MARK]);
+
        if (iif) {
                struct net_device *dev;
                int flags = 0;
index 0d78132ff18aa018fa4e9918dbfb0dd57f95147a..8517d3cd1aed460bbfb1bfb0f515924f008b790d 100644 (file)
@@ -42,7 +42,7 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
        if (NAPI_GRO_CB(skb)->flush)
                goto skip_csum;
 
-       wsum = skb->csum;
+       wsum = NAPI_GRO_CB(skb)->csum;
 
        switch (skb->ip_summed) {
        case CHECKSUM_NONE:
index 19ef329bdbf8e7418fa1d352bb6c90218935831e..b930d080c66f231f338c7ea860c8c1d798d91fea 100644 (file)
@@ -114,12 +114,6 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
        if (err)
                return err;
 
-       memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
-#ifdef CONFIG_NETFILTER
-       IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
-#endif
-
-       skb->protocol = htons(ETH_P_IPV6);
        skb->local_df = 1;
 
        return x->outer_mode->output2(x, skb);
@@ -128,11 +122,13 @@ EXPORT_SYMBOL(xfrm6_prepare_output);
 
 int xfrm6_output_finish(struct sk_buff *skb)
 {
+       memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
+       skb->protocol = htons(ETH_P_IPV6);
+
 #ifdef CONFIG_NETFILTER
        IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
 #endif
 
-       skb->protocol = htons(ETH_P_IPV6);
        return xfrm_output(skb);
 }
 
@@ -142,6 +138,13 @@ static int __xfrm6_output(struct sk_buff *skb)
        struct xfrm_state *x = dst->xfrm;
        int mtu;
 
+#ifdef CONFIG_NETFILTER
+       if (!x) {
+               IP6CB(skb)->flags |= IP6SKB_REROUTED;
+               return dst_output(skb);
+       }
+#endif
+
        if (skb->protocol == htons(ETH_P_IPV6))
                mtu = ip6_skb_dst_mtu(skb);
        else
@@ -165,6 +168,7 @@ static int __xfrm6_output(struct sk_buff *skb)
 
 int xfrm6_output(struct sock *sk, struct sk_buff *skb)
 {
-       return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL,
-                      skb_dst(skb)->dev, __xfrm6_output);
+       return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb,
+                           NULL, skb_dst(skb)->dev, __xfrm6_output,
+                           !(IP6CB(skb)->flags & IP6SKB_REROUTED));
 }
index 6ab989c486f7ee66c5cd6235ce4f758fe9f277a6..54d13f8dbbae10670756eee0b16b898423d06060 100644 (file)
@@ -50,6 +50,10 @@ int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
 {
        int ret;
        struct xfrm6_protocol *handler;
+       struct xfrm6_protocol __rcu **head = proto_handlers(protocol);
+
+       if (!head)
+               return 0;
 
        for_each_protocol_rcu(*proto_handlers(protocol), handler)
                if ((ret = handler->cb_handler(skb, err)) <= 0)
@@ -184,10 +188,12 @@ int xfrm6_protocol_register(struct xfrm6_protocol *handler,
        struct xfrm6_protocol __rcu **pprev;
        struct xfrm6_protocol *t;
        bool add_netproto = false;
-
        int ret = -EEXIST;
        int priority = handler->priority;
 
+       if (!proto_handlers(protocol) || !netproto(protocol))
+               return -EINVAL;
+
        mutex_lock(&xfrm6_protocol_mutex);
 
        if (!rcu_dereference_protected(*proto_handlers(protocol),
@@ -230,6 +236,9 @@ int xfrm6_protocol_deregister(struct xfrm6_protocol *handler,
        struct xfrm6_protocol *t;
        int ret = -ENOENT;
 
+       if (!proto_handlers(protocol) || !netproto(protocol))
+               return -EINVAL;
+
        mutex_lock(&xfrm6_protocol_mutex);
 
        for (pprev = proto_handlers(protocol);
index 01e77b0ae0755d037093e7597a42db2a66378a51..8c9d7302c84682f4eec438405cf312da02cf9aab 100644 (file)
@@ -1830,7 +1830,7 @@ static void iucv_callback_txdone(struct iucv_path *path,
                spin_lock_irqsave(&list->lock, flags);
 
                while (list_skb != (struct sk_buff *)list) {
-                       if (msg->tag != IUCV_SKB_CB(list_skb)->tag) {
+                       if (msg->tag == IUCV_SKB_CB(list_skb)->tag) {
                                this = list_skb;
                                break;
                        }
index 222c28b75315f1ab43226e08566a5f911c6bacc7..f169b6ee94ee8d6ee9c6daa5dc047c5f8b1d2740 100644 (file)
@@ -317,6 +317,7 @@ struct ieee80211_roc_work {
 
        bool started, abort, hw_begun, notified;
        bool to_be_freed;
+       bool on_channel;
 
        unsigned long hw_start_time;
 
index dee50aefd6e868e247ba869e9e9883d4640330e3..27600a9808baeaa31be82ecb0f4218225b28665e 100644 (file)
@@ -3598,18 +3598,24 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata)
 
        sdata_lock(sdata);
 
-       if (ifmgd->auth_data) {
+       if (ifmgd->auth_data || ifmgd->assoc_data) {
+               const u8 *bssid = ifmgd->auth_data ?
+                               ifmgd->auth_data->bss->bssid :
+                               ifmgd->assoc_data->bss->bssid;
+
                /*
-                * If we are trying to authenticate while suspending, cfg80211
-                * won't know and won't actually abort those attempts, thus we
-                * need to do that ourselves.
+                * If we are trying to authenticate / associate while suspending,
+                * cfg80211 won't know and won't actually abort those attempts,
+                * thus we need to do that ourselves.
                 */
-               ieee80211_send_deauth_disassoc(sdata,
-                                              ifmgd->auth_data->bss->bssid,
+               ieee80211_send_deauth_disassoc(sdata, bssid,
                                               IEEE80211_STYPE_DEAUTH,
                                               WLAN_REASON_DEAUTH_LEAVING,
                                               false, frame_buf);
-               ieee80211_destroy_auth_data(sdata, false);
+               if (ifmgd->assoc_data)
+                       ieee80211_destroy_assoc_data(sdata, false);
+               if (ifmgd->auth_data)
+                       ieee80211_destroy_auth_data(sdata, false);
                cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
                                      IEEE80211_DEAUTH_FRAME_LEN);
        }
index 6fb38558a5e6c79d81fc6ba4a4b03ff4313a701a..7a17decd27f91af8646da20b9ab75fc3e303e3c4 100644 (file)
@@ -333,7 +333,7 @@ void ieee80211_sw_roc_work(struct work_struct *work)
                container_of(work, struct ieee80211_roc_work, work.work);
        struct ieee80211_sub_if_data *sdata = roc->sdata;
        struct ieee80211_local *local = sdata->local;
-       bool started;
+       bool started, on_channel;
 
        mutex_lock(&local->mtx);
 
@@ -354,14 +354,26 @@ void ieee80211_sw_roc_work(struct work_struct *work)
        if (!roc->started) {
                struct ieee80211_roc_work *dep;
 
-               /* start this ROC */
-               ieee80211_offchannel_stop_vifs(local);
+               WARN_ON(local->use_chanctx);
+
+               /* If actually operating on the desired channel (with at least
+                * 20 MHz channel width) don't stop all the operations but still
+                * treat it as though the ROC operation started properly, so
+                * other ROC operations won't interfere with this one.
+                */
+               roc->on_channel = roc->chan == local->_oper_chandef.chan &&
+                                 local->_oper_chandef.width != NL80211_CHAN_WIDTH_5 &&
+                                 local->_oper_chandef.width != NL80211_CHAN_WIDTH_10;
 
-               /* switch channel etc */
+               /* start this ROC */
                ieee80211_recalc_idle(local);
 
-               local->tmp_channel = roc->chan;
-               ieee80211_hw_config(local, 0);
+               if (!roc->on_channel) {
+                       ieee80211_offchannel_stop_vifs(local);
+
+                       local->tmp_channel = roc->chan;
+                       ieee80211_hw_config(local, 0);
+               }
 
                /* tell userspace or send frame */
                ieee80211_handle_roc_started(roc);
@@ -380,9 +392,10 @@ void ieee80211_sw_roc_work(struct work_struct *work)
  finish:
                list_del(&roc->list);
                started = roc->started;
+               on_channel = roc->on_channel;
                ieee80211_roc_notify_destroy(roc, !roc->abort);
 
-               if (started) {
+               if (started && !on_channel) {
                        ieee80211_flush_queues(local, NULL);
 
                        local->tmp_channel = NULL;
index 216c45b949e513382447050eb560098a5edaa4b3..2b608b2b70ece8a6ed0cb8f8d8eed5b1d44e1536 100644 (file)
@@ -1231,7 +1231,8 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
                if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) &&
                    test_sta_flag(sta, WLAN_STA_AUTHORIZED)) {
                        sta->last_rx = jiffies;
-                       if (ieee80211_is_data(hdr->frame_control)) {
+                       if (ieee80211_is_data(hdr->frame_control) &&
+                           !is_multicast_ether_addr(hdr->addr1)) {
                                sta->last_rx_rate_idx = status->rate_idx;
                                sta->last_rx_rate_flag = status->flag;
                                sta->last_rx_rate_vht_flag = status->vht_flag;
index 137a192e64bc3c2aa61cc9c5912a89bd3008cbe3..847d92f6bef60856be53ad13f0534695e4c6dac7 100644 (file)
@@ -1148,7 +1148,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
        atomic_dec(&ps->num_sta_ps);
 
        /* This station just woke up and isn't aware of our SMPS state */
-       if (!ieee80211_smps_is_restrictive(sta->known_smps_mode,
+       if (!ieee80211_vif_is_mesh(&sdata->vif) &&
+           !ieee80211_smps_is_restrictive(sta->known_smps_mode,
                                           sdata->smps_mode) &&
            sta->known_smps_mode != sdata->bss->req_smps &&
            sta_info_tx_streams(sta) != 1) {
index 00ba90b02ab2ab79c01d58dc5ba25785993f8dd6..60cb7a665976e10e7a909a9545b7643cf34e67a4 100644 (file)
@@ -314,10 +314,9 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
            !is_multicast_ether_addr(hdr->addr1))
                txflags |= IEEE80211_RADIOTAP_F_TX_FAIL;
 
-       if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
-           (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
+       if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
                txflags |= IEEE80211_RADIOTAP_F_TX_CTS;
-       else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
+       if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
                txflags |= IEEE80211_RADIOTAP_F_TX_RTS;
 
        put_unaligned_le16(txflags, pos);
index a0b0aea76525c341711c129519a1c3f89a704bb9..cec5b60487a4032e2b805df374616ea9ad038669 100644 (file)
 
 #define VIF_ENTRY      __field(enum nl80211_iftype, vif_type) __field(void *, sdata)   \
                        __field(bool, p2p)                                              \
-                       __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>")
+                       __string(vif_name, sdata->name)
 #define VIF_ASSIGN     __entry->vif_type = sdata->vif.type; __entry->sdata = sdata;    \
                        __entry->p2p = sdata->vif.p2p;                                  \
-                       __assign_str(vif_name, sdata->dev ? sdata->dev->name : sdata->name)
+                       __assign_str(vif_name, sdata->name)
 #define VIF_PR_FMT     " vif:%s(%d%s)"
 #define VIF_PR_ARG     __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""
 
index 275c94f995f7c8401749cbbafb249bb52a418be7..3c365837e910edce60ac2348b0002361c4fca6ea 100644 (file)
@@ -1780,7 +1780,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        mutex_unlock(&local->mtx);
 
        if (sched_scan_stopped)
-               cfg80211_sched_scan_stopped(local->hw.wiphy);
+               cfg80211_sched_scan_stopped_rtnl(local->hw.wiphy);
 
        /*
         * If this is for hw restart things are still running.
index e9e36a256165842ac112e35e612ba79c8f86d305..9265adfdabfcf99acbdf1598067884188c500a49 100644 (file)
@@ -129,9 +129,12 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
        if (!vht_cap_ie || !sband->vht_cap.vht_supported)
                return;
 
-       /* A VHT STA must support 40 MHz */
-       if (!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
-               return;
+       /*
+        * A VHT STA must support 40 MHz, but if we verify that here
+        * then we break a few things - some APs (e.g. Netgear R6300v2
+        * and others based on the BCM4360 chipset) will unset this
+        * capability bit when operating in 20 MHz.
+        */
 
        vht_cap->vht_supported = true;
 
index ccc46fa5edbce5e52710a22ae502e49a0f59e0a5..58579634427d2fcbf7f35556424a959697b8655e 100644 (file)
@@ -1336,6 +1336,9 @@ ctnetlink_setup_nat(struct nf_conn *ct, const struct nlattr * const cda[])
 #ifdef CONFIG_NF_NAT_NEEDED
        int ret;
 
+       if (!cda[CTA_NAT_DST] && !cda[CTA_NAT_SRC])
+               return 0;
+
        ret = ctnetlink_parse_nat_setup(ct, NF_NAT_MANIP_DST,
                                        cda[CTA_NAT_DST]);
        if (ret < 0)
index 804105391b9a903354ae9517d602c8c4638a8879..345acfb1720b14f00aae0e5937ab07bfb90e9482 100644 (file)
@@ -66,20 +66,6 @@ struct nft_jumpstack {
        int                     rulenum;
 };
 
-static inline void
-nft_chain_stats(const struct nft_chain *this, const struct nft_pktinfo *pkt,
-               struct nft_jumpstack *jumpstack, unsigned int stackptr)
-{
-       struct nft_stats __percpu *stats;
-       const struct nft_chain *chain = stackptr ? jumpstack[0].chain : this;
-
-       rcu_read_lock_bh();
-       stats = rcu_dereference(nft_base_chain(chain)->stats);
-       __this_cpu_inc(stats->pkts);
-       __this_cpu_add(stats->bytes, pkt->skb->len);
-       rcu_read_unlock_bh();
-}
-
 enum nft_trace {
        NFT_TRACE_RULE,
        NFT_TRACE_RETURN,
@@ -117,13 +103,14 @@ static void nft_trace_packet(const struct nft_pktinfo *pkt,
 unsigned int
 nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
 {
-       const struct nft_chain *chain = ops->priv;
+       const struct nft_chain *chain = ops->priv, *basechain = chain;
        const struct nft_rule *rule;
        const struct nft_expr *expr, *last;
        struct nft_data data[NFT_REG_MAX + 1];
        unsigned int stackptr = 0;
        struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE];
-       int rulenum = 0;
+       struct nft_stats __percpu *stats;
+       int rulenum;
        /*
         * Cache cursor to avoid problems in case that the cursor is updated
         * while traversing the ruleset.
@@ -131,6 +118,7 @@ nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
        unsigned int gencursor = ACCESS_ONCE(chain->net->nft.gencursor);
 
 do_chain:
+       rulenum = 0;
        rule = list_entry(&chain->rules, struct nft_rule, list);
 next_rule:
        data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
@@ -156,8 +144,10 @@ next_rule:
                switch (data[NFT_REG_VERDICT].verdict) {
                case NFT_BREAK:
                        data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
-                       /* fall through */
+                       continue;
                case NFT_CONTINUE:
+                       if (unlikely(pkt->skb->nf_trace))
+                               nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
                        continue;
                }
                break;
@@ -183,37 +173,44 @@ next_rule:
                jumpstack[stackptr].rule  = rule;
                jumpstack[stackptr].rulenum = rulenum;
                stackptr++;
-               /* fall through */
+               chain = data[NFT_REG_VERDICT].chain;
+               goto do_chain;
        case NFT_GOTO:
+               if (unlikely(pkt->skb->nf_trace))
+                       nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
+
                chain = data[NFT_REG_VERDICT].chain;
                goto do_chain;
        case NFT_RETURN:
                if (unlikely(pkt->skb->nf_trace))
                        nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RETURN);
-
-               /* fall through */
+               break;
        case NFT_CONTINUE:
+               if (unlikely(pkt->skb->nf_trace && !(chain->flags & NFT_BASE_CHAIN)))
+                       nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_RETURN);
                break;
        default:
                WARN_ON(1);
        }
 
        if (stackptr > 0) {
-               if (unlikely(pkt->skb->nf_trace))
-                       nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_RETURN);
-
                stackptr--;
                chain = jumpstack[stackptr].chain;
                rule  = jumpstack[stackptr].rule;
                rulenum = jumpstack[stackptr].rulenum;
                goto next_rule;
        }
-       nft_chain_stats(chain, pkt, jumpstack, stackptr);
 
        if (unlikely(pkt->skb->nf_trace))
-               nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_POLICY);
+               nft_trace_packet(pkt, basechain, -1, NFT_TRACE_POLICY);
+
+       rcu_read_lock_bh();
+       stats = rcu_dereference(nft_base_chain(basechain)->stats);
+       __this_cpu_inc(stats->pkts);
+       __this_cpu_add(stats->bytes, pkt->skb->len);
+       rcu_read_unlock_bh();
 
-       return nft_base_chain(chain)->policy;
+       return nft_base_chain(basechain)->policy;
 }
 EXPORT_SYMBOL_GPL(nft_do_chain);
 
index e8138da4c14f70f40449c72ec4dc4d31f2960b8e..23ef77c60fffc60a1678f79dfbb769fe9be6a274 100644 (file)
@@ -256,15 +256,15 @@ replay:
 #endif
                {
                        nfnl_unlock(subsys_id);
-                       kfree_skb(nskb);
-                       return netlink_ack(skb, nlh, -EOPNOTSUPP);
+                       netlink_ack(skb, nlh, -EOPNOTSUPP);
+                       return kfree_skb(nskb);
                }
        }
 
        if (!ss->commit || !ss->abort) {
                nfnl_unlock(subsys_id);
-               kfree_skb(nskb);
-               return netlink_ack(skb, nlh, -EOPNOTSUPP);
+               netlink_ack(skb, nlh, -EOPNOTSUPP);
+               return kfree_skb(skb);
        }
 
        while (skb->len >= nlmsg_total_size(0)) {
@@ -368,14 +368,13 @@ done:
 static void nfnetlink_rcv(struct sk_buff *skb)
 {
        struct nlmsghdr *nlh = nlmsg_hdr(skb);
-       struct net *net = sock_net(skb->sk);
        int msglen;
 
        if (nlh->nlmsg_len < NLMSG_HDRLEN ||
            skb->len < nlh->nlmsg_len)
                return;
 
-       if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) {
+       if (!netlink_net_capable(skb, CAP_NET_ADMIN)) {
                netlink_ack(skb, nlh, -EPERM);
                return;
        }
index 894cda0206bb9b8a32488ec81959482a7cc582d5..81dca96d2be682afde14169615b50fb73626c662 100644 (file)
@@ -1360,7 +1360,72 @@ retry:
        return err;
 }
 
-static inline int netlink_capable(const struct socket *sock, unsigned int flag)
+/**
+ * __netlink_ns_capable - General netlink message capability test
+ * @nsp: NETLINK_CB of the socket buffer holding a netlink command from userspace.
+ * @user_ns: The user namespace of the capability to use
+ * @cap: The capability to use
+ *
+ * Test to see if the opener of the socket we received the message
+ * from had when the netlink socket was created and the sender of the
+ * message has has the capability @cap in the user namespace @user_ns.
+ */
+bool __netlink_ns_capable(const struct netlink_skb_parms *nsp,
+                       struct user_namespace *user_ns, int cap)
+{
+       return sk_ns_capable(nsp->sk, user_ns, cap);
+}
+EXPORT_SYMBOL(__netlink_ns_capable);
+
+/**
+ * netlink_ns_capable - General netlink message capability test
+ * @skb: socket buffer holding a netlink command from userspace
+ * @user_ns: The user namespace of the capability to use
+ * @cap: The capability to use
+ *
+ * Test to see if the opener of the socket we received the message
+ * from had when the netlink socket was created and the sender of the
+ * message has has the capability @cap in the user namespace @user_ns.
+ */
+bool netlink_ns_capable(const struct sk_buff *skb,
+                       struct user_namespace *user_ns, int cap)
+{
+       return __netlink_ns_capable(&NETLINK_CB(skb), user_ns, cap);
+}
+EXPORT_SYMBOL(netlink_ns_capable);
+
+/**
+ * netlink_capable - Netlink global message capability test
+ * @skb: socket buffer holding a netlink command from userspace
+ * @cap: The capability to use
+ *
+ * Test to see if the opener of the socket we received the message
+ * from had when the netlink socket was created and the sender of the
+ * message has has the capability @cap in all user namespaces.
+ */
+bool netlink_capable(const struct sk_buff *skb, int cap)
+{
+       return netlink_ns_capable(skb, &init_user_ns, cap);
+}
+EXPORT_SYMBOL(netlink_capable);
+
+/**
+ * netlink_net_capable - Netlink network namespace message capability test
+ * @skb: socket buffer holding a netlink command from userspace
+ * @cap: The capability to use
+ *
+ * Test to see if the opener of the socket we received the message
+ * from had when the netlink socket was created and the sender of the
+ * message has has the capability @cap over the network namespace of
+ * the socket we received the message from.
+ */
+bool netlink_net_capable(const struct sk_buff *skb, int cap)
+{
+       return netlink_ns_capable(skb, sock_net(skb->sk)->user_ns, cap);
+}
+EXPORT_SYMBOL(netlink_net_capable);
+
+static inline int netlink_allowed(const struct socket *sock, unsigned int flag)
 {
        return (nl_table[sock->sk->sk_protocol].flags & flag) ||
                ns_capable(sock_net(sock->sk)->user_ns, CAP_NET_ADMIN);
@@ -1428,7 +1493,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
 
        /* Only superuser is allowed to listen multicasts */
        if (nladdr->nl_groups) {
-               if (!netlink_capable(sock, NL_CFG_F_NONROOT_RECV))
+               if (!netlink_allowed(sock, NL_CFG_F_NONROOT_RECV))
                        return -EPERM;
                err = netlink_realloc_groups(sk);
                if (err)
@@ -1490,7 +1555,7 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr,
                return -EINVAL;
 
        if ((nladdr->nl_groups || nladdr->nl_pid) &&
-           !netlink_capable(sock, NL_CFG_F_NONROOT_SEND))
+           !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND))
                return -EPERM;
 
        if (!nlk->portid)
@@ -2096,7 +2161,7 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
                break;
        case NETLINK_ADD_MEMBERSHIP:
        case NETLINK_DROP_MEMBERSHIP: {
-               if (!netlink_capable(sock, NL_CFG_F_NONROOT_RECV))
+               if (!netlink_allowed(sock, NL_CFG_F_NONROOT_RECV))
                        return -EPERM;
                err = netlink_realloc_groups(sk);
                if (err)
@@ -2247,7 +2312,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
                dst_group = ffs(addr->nl_groups);
                err =  -EPERM;
                if ((dst_group || dst_portid) &&
-                   !netlink_capable(sock, NL_CFG_F_NONROOT_SEND))
+                   !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND))
                        goto out;
        } else {
                dst_portid = nlk->dst_portid;
index b1dcdb932a86ee919642f47f58dd3b716995ad76..a3ba3ca0ff9281dec15c0b4d42002394583c1d8d 100644 (file)
@@ -561,7 +561,7 @@ static int genl_family_rcv_msg(struct genl_family *family,
                return -EOPNOTSUPP;
 
        if ((ops->flags & GENL_ADMIN_PERM) &&
-           !capable(CAP_NET_ADMIN))
+           !netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
        if ((nlh->nlmsg_flags & NLM_F_DUMP) == NLM_F_DUMP) {
index 533ce4ff108ad94ff0a1e5205bc17f9c91c0b3ce..92f2c7107eec4f307cc50cdfedfb4ea2db0e59de 100644 (file)
@@ -128,6 +128,7 @@ static int pdiag_put_fanout(struct packet_sock *po, struct sk_buff *nlskb)
 
 static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
                        struct packet_diag_req *req,
+                       bool may_report_filterinfo,
                        struct user_namespace *user_ns,
                        u32 portid, u32 seq, u32 flags, int sk_ino)
 {
@@ -172,7 +173,8 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
                goto out_nlmsg_trim;
 
        if ((req->pdiag_show & PACKET_SHOW_FILTER) &&
-           sock_diag_put_filterinfo(user_ns, sk, skb, PACKET_DIAG_FILTER))
+           sock_diag_put_filterinfo(may_report_filterinfo, sk, skb,
+                                    PACKET_DIAG_FILTER))
                goto out_nlmsg_trim;
 
        return nlmsg_end(skb, nlh);
@@ -188,9 +190,11 @@ static int packet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
        struct packet_diag_req *req;
        struct net *net;
        struct sock *sk;
+       bool may_report_filterinfo;
 
        net = sock_net(skb->sk);
        req = nlmsg_data(cb->nlh);
+       may_report_filterinfo = netlink_net_capable(cb->skb, CAP_NET_ADMIN);
 
        mutex_lock(&net->packet.sklist_lock);
        sk_for_each(sk, &net->packet.sklist) {
@@ -200,6 +204,7 @@ static int packet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
                        goto next;
 
                if (sk_diag_fill(sk, skb, req,
+                                may_report_filterinfo,
                                 sk_user_ns(NETLINK_CB(cb->skb).sk),
                                 NETLINK_CB(cb->skb).portid,
                                 cb->nlh->nlmsg_seq, NLM_F_MULTI,
index dc15f430080831e74fade00799a661ab10cc6f84..b64151ade6b33a9cbacb0980d3ddbe03d8f7b4c8 100644 (file)
@@ -70,10 +70,10 @@ static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh)
        int err;
        u8 pnaddr;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
-       if (!capable(CAP_SYS_ADMIN))
+       if (!netlink_capable(skb, CAP_SYS_ADMIN))
                return -EPERM;
 
        ASSERT_RTNL();
@@ -233,10 +233,10 @@ static int route_doit(struct sk_buff *skb, struct nlmsghdr *nlh)
        int err;
        u8 dst;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
-       if (!capable(CAP_SYS_ADMIN))
+       if (!netlink_capable(skb, CAP_SYS_ADMIN))
                return -EPERM;
 
        ASSERT_RTNL();
index 7633a752c65e99189c3e7603e2ebdd6e7438b356..0ad080790a32a341a1ddc57d632302563964a247 100644 (file)
@@ -99,7 +99,7 @@ static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr,
        _debug("tktlen: %x", tktlen);
        if (tktlen > AFSTOKEN_RK_TIX_MAX)
                return -EKEYREJECTED;
-       if (8 * 4 + tktlen != toklen)
+       if (toklen < 8 * 4 + tktlen)
                return -EKEYREJECTED;
 
        plen = sizeof(*token) + sizeof(*token->kad) + tktlen;
index 8a5ba5add4bcd60e59a9b2468df88812212012f4..648778aef1a254b9739443e93012798a134d0d86 100644 (file)
@@ -948,7 +948,7 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n)
        u32 portid = skb ? NETLINK_CB(skb).portid : 0;
        int ret = 0, ovr = 0;
 
-       if ((n->nlmsg_type != RTM_GETACTION) && !capable(CAP_NET_ADMIN))
+       if ((n->nlmsg_type != RTM_GETACTION) && !netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
        ret = nlmsg_parse(n, sizeof(struct tcamsg), tca, TCA_ACT_MAX, NULL);
index 29a30a14c31596cc51028be8db46eb4df9756f6e..bdbdb1a7920af99c1829ae62716caddafb114fef 100644 (file)
@@ -134,7 +134,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
        int err;
        int tp_created = 0;
 
-       if ((n->nlmsg_type != RTM_GETTFILTER) && !capable(CAP_NET_ADMIN))
+       if ((n->nlmsg_type != RTM_GETTFILTER) && !netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
 replay:
index eed8404443d8f0145942c3e459b79934ada9c48d..f435a88d899afff7c132085ccece5427461e5490 100644 (file)
@@ -188,6 +188,12 @@ static const struct nla_policy tcindex_policy[TCA_TCINDEX_MAX + 1] = {
        [TCA_TCINDEX_CLASSID]           = { .type = NLA_U32 },
 };
 
+static void tcindex_filter_result_init(struct tcindex_filter_result *r)
+{
+       memset(r, 0, sizeof(*r));
+       tcf_exts_init(&r->exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
+}
+
 static int
 tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
                  u32 handle, struct tcindex_data *p,
@@ -207,15 +213,11 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
                return err;
 
        memcpy(&cp, p, sizeof(cp));
-       memset(&new_filter_result, 0, sizeof(new_filter_result));
-       tcf_exts_init(&new_filter_result.exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
+       tcindex_filter_result_init(&new_filter_result);
 
+       tcindex_filter_result_init(&cr);
        if (old_r)
-               memcpy(&cr, r, sizeof(cr));
-       else {
-               memset(&cr, 0, sizeof(cr));
-               tcf_exts_init(&cr.exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
-       }
+               cr.res = r->res;
 
        if (tb[TCA_TCINDEX_HASH])
                cp.hash = nla_get_u32(tb[TCA_TCINDEX_HASH]);
@@ -267,9 +269,14 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        err = -ENOMEM;
        if (!cp.perfect && !cp.h) {
                if (valid_perfect_hash(&cp)) {
+                       int i;
+
                        cp.perfect = kcalloc(cp.hash, sizeof(*r), GFP_KERNEL);
                        if (!cp.perfect)
                                goto errout;
+                       for (i = 0; i < cp.hash; i++)
+                               tcf_exts_init(&cp.perfect[i].exts, TCA_TCINDEX_ACT,
+                                             TCA_TCINDEX_POLICE);
                        balloc = 1;
                } else {
                        cp.h = kcalloc(cp.hash, sizeof(f), GFP_KERNEL);
@@ -295,14 +302,17 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
                tcf_bind_filter(tp, &cr.res, base);
        }
 
-       tcf_exts_change(tp, &cr.exts, &e);
+       if (old_r)
+               tcf_exts_change(tp, &r->exts, &e);
+       else
+               tcf_exts_change(tp, &cr.exts, &e);
 
        tcf_tree_lock(tp);
        if (old_r && old_r != r)
-               memset(old_r, 0, sizeof(*old_r));
+               tcindex_filter_result_init(old_r);
 
        memcpy(p, &cp, sizeof(cp));
-       memcpy(r, &cr, sizeof(cr));
+       r->res = cr.res;
 
        if (r == &new_filter_result) {
                struct tcindex_filter **fp;
index a0b84e0e22deb4c9e998499b1e202ebaafda95f8..400769014bbde8d4e9032600524e97f549dcff31 100644 (file)
@@ -1084,7 +1084,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n)
        struct Qdisc *p = NULL;
        int err;
 
-       if ((n->nlmsg_type != RTM_GETQDISC) && !capable(CAP_NET_ADMIN))
+       if ((n->nlmsg_type != RTM_GETQDISC) && !netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
        err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
@@ -1151,7 +1151,7 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n)
        struct Qdisc *q, *p;
        int err;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
 replay:
@@ -1490,7 +1490,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n)
        u32 qid;
        int err;
 
-       if ((n->nlmsg_type != RTM_GETTCLASS) && !capable(CAP_NET_ADMIN))
+       if ((n->nlmsg_type != RTM_GETTCLASS) && !netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
        err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
index edee03d922e28678cc4f4ba843f600236cf06f08..6e957c3b9854acc025e43d9028b94f0af7f4d6c1 100644 (file)
@@ -553,11 +553,6 @@ static int hhf_change(struct Qdisc *sch, struct nlattr *opt)
        if (err < 0)
                return err;
 
-       sch_tree_lock(sch);
-
-       if (tb[TCA_HHF_BACKLOG_LIMIT])
-               sch->limit = nla_get_u32(tb[TCA_HHF_BACKLOG_LIMIT]);
-
        if (tb[TCA_HHF_QUANTUM])
                new_quantum = nla_get_u32(tb[TCA_HHF_QUANTUM]);
 
@@ -567,6 +562,12 @@ static int hhf_change(struct Qdisc *sch, struct nlattr *opt)
        non_hh_quantum = (u64)new_quantum * new_hhf_non_hh_weight;
        if (non_hh_quantum > INT_MAX)
                return -EINVAL;
+
+       sch_tree_lock(sch);
+
+       if (tb[TCA_HHF_BACKLOG_LIMIT])
+               sch->limit = nla_get_u32(tb[TCA_HHF_BACKLOG_LIMIT]);
+
        q->quantum = new_quantum;
        q->hhf_non_hh_weight = new_hhf_non_hh_weight;
 
index c09757fbf8039e76c935c1dbf33ab2b19be228b1..44cbb54c85746a586407015c952e7f8d60ab4d91 100644 (file)
@@ -491,8 +491,13 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
                        continue;
                if ((laddr->state == SCTP_ADDR_SRC) &&
                    (AF_INET == laddr->a.sa.sa_family)) {
-                       fl4->saddr = laddr->a.v4.sin_addr.s_addr;
                        fl4->fl4_sport = laddr->a.v4.sin_port;
+                       flowi4_update_output(fl4,
+                                            asoc->base.sk->sk_bound_dev_if,
+                                            RT_CONN_FLAGS(asoc->base.sk),
+                                            daddr->v4.sin_addr.s_addr,
+                                            laddr->a.v4.sin_addr.s_addr);
+
                        rt = ip_route_output_key(sock_net(sk), fl4);
                        if (!IS_ERR(rt)) {
                                dst = &rt->dst;
index 5d6883ff00c3b7056639f06254caffcb14349e27..fef2acdf4a2e675c55dc9fbf2124d132499b89e3 100644 (file)
@@ -496,11 +496,10 @@ static void sctp_do_8_2_transport_strike(sctp_cmd_seq_t *commands,
 
        /* If the transport error count is greater than the pf_retrans
         * threshold, and less than pathmaxrtx, and if the current state
-        * is not SCTP_UNCONFIRMED, then mark this transport as Partially
-        * Failed, see SCTP Quick Failover Draft, section 5.1
+        * is SCTP_ACTIVE, then mark this transport as Partially Failed,
+        * see SCTP Quick Failover Draft, section 5.1
         */
-       if ((transport->state != SCTP_PF) &&
-          (transport->state != SCTP_UNCONFIRMED) &&
+       if ((transport->state == SCTP_ACTIVE) &&
           (asoc->pf_retrans < transport->pathmaxrxt) &&
           (transport->error_count > asoc->pf_retrans)) {
 
index 3aaf73de9e2d017e96b3cc1124d5c9420d827abd..ad844d3653409a6f5ad2ceac53e1b52dc48eacaa 100644 (file)
@@ -47,7 +47,7 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
        int hdr_space = nlmsg_total_size(GENL_HDRLEN + TIPC_GENL_HDRLEN);
        u16 cmd;
 
-       if ((req_userhdr->cmd & 0xC000) && (!capable(CAP_NET_ADMIN)))
+       if ((req_userhdr->cmd & 0xC000) && (!netlink_capable(skb, CAP_NET_ADMIN)))
                cmd = TIPC_CMD_NOT_NET_ADMIN;
        else
                cmd = req_userhdr->cmd;
index 5adfd94c5b85d3d48a6d48d3a4c7c2fa98526d8b..85d232bed87d21f3c23cd695b83defef5a6f22c1 100644 (file)
@@ -1925,9 +1925,23 @@ static struct miscdevice vsock_device = {
        .fops           = &vsock_device_ops,
 };
 
-static int __vsock_core_init(void)
+int __vsock_core_init(const struct vsock_transport *t, struct module *owner)
 {
-       int err;
+       int err = mutex_lock_interruptible(&vsock_register_mutex);
+
+       if (err)
+               return err;
+
+       if (transport) {
+               err = -EBUSY;
+               goto err_busy;
+       }
+
+       /* Transport must be the owner of the protocol so that it can't
+        * unload while there are open sockets.
+        */
+       vsock_proto.owner = owner;
+       transport = t;
 
        vsock_init_tables();
 
@@ -1951,36 +1965,19 @@ static int __vsock_core_init(void)
                goto err_unregister_proto;
        }
 
+       mutex_unlock(&vsock_register_mutex);
        return 0;
 
 err_unregister_proto:
        proto_unregister(&vsock_proto);
 err_misc_deregister:
        misc_deregister(&vsock_device);
-       return err;
-}
-
-int vsock_core_init(const struct vsock_transport *t)
-{
-       int retval = mutex_lock_interruptible(&vsock_register_mutex);
-       if (retval)
-               return retval;
-
-       if (transport) {
-               retval = -EBUSY;
-               goto out;
-       }
-
-       transport = t;
-       retval = __vsock_core_init();
-       if (retval)
-               transport = NULL;
-
-out:
+       transport = NULL;
+err_busy:
        mutex_unlock(&vsock_register_mutex);
-       return retval;
+       return err;
 }
-EXPORT_SYMBOL_GPL(vsock_core_init);
+EXPORT_SYMBOL_GPL(__vsock_core_init);
 
 void vsock_core_exit(void)
 {
@@ -2000,5 +1997,5 @@ EXPORT_SYMBOL_GPL(vsock_core_exit);
 
 MODULE_AUTHOR("VMware, Inc.");
 MODULE_DESCRIPTION("VMware Virtual Socket Family");
-MODULE_VERSION("1.0.0.0-k");
+MODULE_VERSION("1.0.1.0-k");
 MODULE_LICENSE("GPL v2");
index 7d09a712cb1f1353f13310f5c68b38e750d199a6..88f108edfb586ef3b2d17d15cf66b00da84f93f0 100644 (file)
@@ -284,14 +284,22 @@ void cfg80211_sched_scan_results(struct wiphy *wiphy)
 }
 EXPORT_SYMBOL(cfg80211_sched_scan_results);
 
-void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
+void cfg80211_sched_scan_stopped_rtnl(struct wiphy *wiphy)
 {
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
+       ASSERT_RTNL();
+
        trace_cfg80211_sched_scan_stopped(wiphy);
 
-       rtnl_lock();
        __cfg80211_stop_sched_scan(rdev, true);
+}
+EXPORT_SYMBOL(cfg80211_sched_scan_stopped_rtnl);
+
+void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
+{
+       rtnl_lock();
+       cfg80211_sched_scan_stopped_rtnl(wiphy);
        rtnl_unlock();
 }
 EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
index acdcb4a81817b7c78e8e721ff632284b9b806fa9..3546a77033de30d0d2593c6ac4fbac8f58659025 100644 (file)
@@ -234,7 +234,6 @@ void cfg80211_conn_work(struct work_struct *work)
                                        NULL, 0, NULL, 0,
                                        WLAN_STATUS_UNSPECIFIED_FAILURE,
                                        false, NULL);
-                       cfg80211_sme_free(wdev);
                }
                wdev_unlock(wdev);
        }
@@ -648,6 +647,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
                        cfg80211_unhold_bss(bss_from_pub(bss));
                        cfg80211_put_bss(wdev->wiphy, bss);
                }
+               cfg80211_sme_free(wdev);
                return;
        }
 
index 8f131c10a6f3d6793c6d0a049108ab66ccaa8664..51398ae6cda85000b5edc416e9569659495a6614 100644 (file)
@@ -2377,7 +2377,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        link = &xfrm_dispatch[type];
 
        /* All operations require privileges, even GET */
-       if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
+       if (!netlink_net_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
        if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) ||
index fd8fa9aa7c4edd698430a9cb0647a8d26095a9a2..5b3add31f9f1202610e67e4d4868598e5846e594 100755 (executable)
@@ -25,7 +25,7 @@ cat << EOF
 #define __IGNORE_rmdir         /* unlinkat */
 #define __IGNORE_lchown                /* fchownat */
 #define __IGNORE_access                /* faccessat */
-#define __IGNORE_rename                /* renameat */
+#define __IGNORE_rename                /* renameat2 */
 #define __IGNORE_readlink      /* readlinkat */
 #define __IGNORE_symlink       /* symlinkat */
 #define __IGNORE_utimes                /* futimesat */
@@ -37,6 +37,9 @@ cat << EOF
 #define __IGNORE_lstat64       /* fstatat64 */
 #endif
 
+/* Missing flags argument */
+#define __IGNORE_renameat      /* renameat2 */
+
 /* CLOEXEC flag */
 #define __IGNORE_pipe          /* pipe2 */
 #define __IGNORE_dup2          /* dup3 */
index cc49062acdeecf85259f646df09abe22f1019a5d..1052d4834a44f502bda4f4f1ebe1202ace1608f5 100644 (file)
 #define EM_ARCOMPACT   93
 #endif
 
+#ifndef EM_XTENSA
+#define EM_XTENSA      94
+#endif
+
 #ifndef EM_AARCH64
 #define EM_AARCH64     183
 #endif
@@ -281,6 +285,7 @@ do_file(char const *const fname)
        case EM_AARCH64:
        case EM_MICROBLAZE:
        case EM_MIPS:
+       case EM_XTENSA:
                break;
        }  /* end switch */
 
index 8fb1488a3cd4499ecf8e374dcd47f956945a0ef7..97130f88838bc2ad385b5ccd69bf0dfc51acae95 100644 (file)
@@ -66,7 +66,6 @@ extern int apparmor_initialized __initdata;
 char *aa_split_fqname(char *args, char **ns_name);
 void aa_info_message(const char *str);
 void *__aa_kvmalloc(size_t size, gfp_t flags);
-void kvfree(void *buffer);
 
 static inline void *kvmalloc(size_t size)
 {
index 69689922c491b8a4eeda5d96115df4a49e6a844f..c1827e068454cf992c510fd7f6bc9cbbda67a500 100644 (file)
@@ -104,17 +104,3 @@ void *__aa_kvmalloc(size_t size, gfp_t flags)
        }
        return buffer;
 }
-
-/**
- * kvfree - free an allocation do by kvmalloc
- * @buffer: buffer to free (MAYBE_NULL)
- *
- * Free a buffer allocated by kvmalloc
- */
-void kvfree(void *buffer)
-{
-       if (is_vmalloc_addr(buffer))
-               vfree(buffer);
-       else
-               kfree(buffer);
-}
index 8365909f5f8cfc6f404fe5ce21b936884298d13f..9134dbf70d3ee6898664f895905c8452e89a01c3 100644 (file)
@@ -306,57 +306,138 @@ static int devcgroup_seq_show(struct seq_file *m, void *v)
 }
 
 /**
- * may_access - verifies if a new exception is part of what is allowed
- *             by a dev cgroup based on the default policy +
- *             exceptions. This is used to make sure a child cgroup
- *             won't have more privileges than its parent or to
- *             verify if a certain access is allowed.
- * @dev_cgroup: dev cgroup to be tested against
- * @refex: new exception
- * @behavior: behavior of the exception
+ * match_exception     - iterates the exception list trying to find a complete match
+ * @exceptions: list of exceptions
+ * @type: device type (DEV_BLOCK or DEV_CHAR)
+ * @major: device file major number, ~0 to match all
+ * @minor: device file minor number, ~0 to match all
+ * @access: permission mask (ACC_READ, ACC_WRITE, ACC_MKNOD)
+ *
+ * It is considered a complete match if an exception is found that will
+ * contain the entire range of provided parameters.
+ *
+ * Return: true in case it matches an exception completely
  */
-static bool may_access(struct dev_cgroup *dev_cgroup,
-                      struct dev_exception_item *refex,
-                      enum devcg_behavior behavior)
+static bool match_exception(struct list_head *exceptions, short type,
+                           u32 major, u32 minor, short access)
 {
        struct dev_exception_item *ex;
-       bool match = false;
 
-       rcu_lockdep_assert(rcu_read_lock_held() ||
-                          lockdep_is_held(&devcgroup_mutex),
-                          "device_cgroup::may_access() called without proper synchronization");
+       list_for_each_entry_rcu(ex, exceptions, list) {
+               if ((type & DEV_BLOCK) && !(ex->type & DEV_BLOCK))
+                       continue;
+               if ((type & DEV_CHAR) && !(ex->type & DEV_CHAR))
+                       continue;
+               if (ex->major != ~0 && ex->major != major)
+                       continue;
+               if (ex->minor != ~0 && ex->minor != minor)
+                       continue;
+               /* provided access cannot have more than the exception rule */
+               if (access & (~ex->access))
+                       continue;
+               return true;
+       }
+       return false;
+}
+
+/**
+ * match_exception_partial - iterates the exception list trying to find a partial match
+ * @exceptions: list of exceptions
+ * @type: device type (DEV_BLOCK or DEV_CHAR)
+ * @major: device file major number, ~0 to match all
+ * @minor: device file minor number, ~0 to match all
+ * @access: permission mask (ACC_READ, ACC_WRITE, ACC_MKNOD)
+ *
+ * It is considered a partial match if an exception's range is found to
+ * contain *any* of the devices specified by provided parameters. This is
+ * used to make sure no extra access is being granted that is forbidden by
+ * any of the exception list.
+ *
+ * Return: true in case the provided range mat matches an exception completely
+ */
+static bool match_exception_partial(struct list_head *exceptions, short type,
+                                   u32 major, u32 minor, short access)
+{
+       struct dev_exception_item *ex;
 
-       list_for_each_entry_rcu(ex, &dev_cgroup->exceptions, list) {
-               if ((refex->type & DEV_BLOCK) && !(ex->type & DEV_BLOCK))
+       list_for_each_entry_rcu(ex, exceptions, list) {
+               if ((type & DEV_BLOCK) && !(ex->type & DEV_BLOCK))
                        continue;
-               if ((refex->type & DEV_CHAR) && !(ex->type & DEV_CHAR))
+               if ((type & DEV_CHAR) && !(ex->type & DEV_CHAR))
                        continue;
-               if (ex->major != ~0 && ex->major != refex->major)
+               /*
+                * We must be sure that both the exception and the provided
+                * range aren't masking all devices
+                */
+               if (ex->major != ~0 && major != ~0 && ex->major != major)
                        continue;
-               if (ex->minor != ~0 && ex->minor != refex->minor)
+               if (ex->minor != ~0 && minor != ~0 && ex->minor != minor)
                        continue;
-               if (refex->access & (~ex->access))
+               /*
+                * In order to make sure the provided range isn't matching
+                * an exception, all its access bits shouldn't match the
+                * exception's access bits
+                */
+               if (!(access & ex->access))
                        continue;
-               match = true;
-               break;
+               return true;
        }
+       return false;
+}
+
+/**
+ * verify_new_ex - verifies if a new exception is allowed by parent cgroup's permissions
+ * @dev_cgroup: dev cgroup to be tested against
+ * @refex: new exception
+ * @behavior: behavior of the exception's dev_cgroup
+ *
+ * This is used to make sure a child cgroup won't have more privileges
+ * than its parent
+ */
+static bool verify_new_ex(struct dev_cgroup *dev_cgroup,
+                         struct dev_exception_item *refex,
+                         enum devcg_behavior behavior)
+{
+       bool match = false;
+
+       rcu_lockdep_assert(rcu_read_lock_held() ||
+                          lockdep_is_held(&devcgroup_mutex),
+                          "device_cgroup:verify_new_ex called without proper synchronization");
 
        if (dev_cgroup->behavior == DEVCG_DEFAULT_ALLOW) {
                if (behavior == DEVCG_DEFAULT_ALLOW) {
-                       /* the exception will deny access to certain devices */
+                       /*
+                        * new exception in the child doesn't matter, only
+                        * adding extra restrictions
+                        */ 
                        return true;
                } else {
-                       /* the exception will allow access to certain devices */
+                       /*
+                        * new exception in the child will add more devices
+                        * that can be acessed, so it can't match any of
+                        * parent's exceptions, even slightly
+                        */ 
+                       match = match_exception_partial(&dev_cgroup->exceptions,
+                                                       refex->type,
+                                                       refex->major,
+                                                       refex->minor,
+                                                       refex->access);
+
                        if (match)
-                               /*
-                                * a new exception allowing access shouldn't
-                                * match an parent's exception
-                                */
                                return false;
                        return true;
                }
        } else {
-               /* only behavior == DEVCG_DEFAULT_DENY allowed here */
+               /*
+                * Only behavior == DEVCG_DEFAULT_DENY allowed here, therefore
+                * the new exception will add access to more devices and must
+                * be contained completely in an parent's exception to be
+                * allowed
+                */
+               match = match_exception(&dev_cgroup->exceptions, refex->type,
+                                       refex->major, refex->minor,
+                                       refex->access);
+
                if (match)
                        /* parent has an exception that matches the proposed */
                        return true;
@@ -378,7 +459,38 @@ static int parent_has_perm(struct dev_cgroup *childcg,
 
        if (!parent)
                return 1;
-       return may_access(parent, ex, childcg->behavior);
+       return verify_new_ex(parent, ex, childcg->behavior);
+}
+
+/**
+ * parent_allows_removal - verify if it's ok to remove an exception
+ * @childcg: child cgroup from where the exception will be removed
+ * @ex: exception being removed
+ *
+ * When removing an exception in cgroups with default ALLOW policy, it must
+ * be checked if removing it will give the child cgroup more access than the
+ * parent.
+ *
+ * Return: true if it's ok to remove exception, false otherwise
+ */
+static bool parent_allows_removal(struct dev_cgroup *childcg,
+                                 struct dev_exception_item *ex)
+{
+       struct dev_cgroup *parent = css_to_devcgroup(css_parent(&childcg->css));
+
+       if (!parent)
+               return true;
+
+       /* It's always allowed to remove access to devices */
+       if (childcg->behavior == DEVCG_DEFAULT_DENY)
+               return true;
+
+       /*
+        * Make sure you're not removing part or a whole exception existing in
+        * the parent cgroup
+        */
+       return !match_exception_partial(&parent->exceptions, ex->type,
+                                       ex->major, ex->minor, ex->access);
 }
 
 /**
@@ -616,17 +728,21 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
 
        switch (filetype) {
        case DEVCG_ALLOW:
-               if (!parent_has_perm(devcgroup, &ex))
-                       return -EPERM;
                /*
                 * If the default policy is to allow by default, try to remove
                 * an matching exception instead. And be silent about it: we
                 * don't want to break compatibility
                 */
                if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) {
+                       /* Check if the parent allows removing it first */
+                       if (!parent_allows_removal(devcgroup, &ex))
+                               return -EPERM;
                        dev_exception_rm(devcgroup, &ex);
-                       return 0;
+                       break;
                }
+
+               if (!parent_has_perm(devcgroup, &ex))
+                       return -EPERM;
                rc = dev_exception_add(devcgroup, &ex);
                break;
        case DEVCG_DENY:
@@ -704,18 +820,18 @@ static int __devcgroup_check_permission(short type, u32 major, u32 minor,
                                        short access)
 {
        struct dev_cgroup *dev_cgroup;
-       struct dev_exception_item ex;
-       int rc;
-
-       memset(&ex, 0, sizeof(ex));
-       ex.type = type;
-       ex.major = major;
-       ex.minor = minor;
-       ex.access = access;
+       bool rc;
 
        rcu_read_lock();
        dev_cgroup = task_devcgroup(current);
-       rc = may_access(dev_cgroup, &ex, dev_cgroup->behavior);
+       if (dev_cgroup->behavior == DEVCG_DEFAULT_ALLOW)
+               /* Can't match any of the exceptions, even partially */
+               rc = !match_exception_partial(&dev_cgroup->exceptions,
+                                             type, major, minor, access);
+       else
+               /* Need to match completely one exception to be allowed */
+               rc = match_exception(&dev_cgroup->exceptions, type, major,
+                                    minor, access);
        rcu_read_unlock();
 
        if (!rc)
index 94d08733cb388cdda361e509701da59650714eeb..76cbb9ec953a0da66b403aa41687f2af93c0f690 100644 (file)
@@ -182,6 +182,7 @@ static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
 int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
        struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
        int ret;
 
        switch (cmd) {
@@ -196,6 +197,11 @@ int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
                dmaengine_resume(prtd->dma_chan);
                break;
        case SNDRV_PCM_TRIGGER_SUSPEND:
+               if (runtime->info & SNDRV_PCM_INFO_PAUSE)
+                       dmaengine_pause(prtd->dma_chan);
+               else
+                       dmaengine_terminate_all(prtd->dma_chan);
+               break;
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                dmaengine_pause(prtd->dma_chan);
                break;
index 6496822c1808b53c172d56df4382fb88e9e20e95..1ff78ec9f0ac508734d536afbe187b9039127e14 100644 (file)
@@ -818,12 +818,14 @@ int snd_sbmixer_new(struct snd_sb *chip)
                        return err;
                break;
        case SB_HW_DT019X:
-               if ((err = snd_sbmixer_init(chip,
-                                           snd_dt019x_controls,
-                                           ARRAY_SIZE(snd_dt019x_controls),
-                                           snd_dt019x_init_values,
-                                           ARRAY_SIZE(snd_dt019x_init_values),
-                                           "DT019X")) < 0)
+               err = snd_sbmixer_init(chip,
+                                      snd_dt019x_controls,
+                                      ARRAY_SIZE(snd_dt019x_controls),
+                                      snd_dt019x_init_values,
+                                      ARRAY_SIZE(snd_dt019x_init_values),
+                                      "DT019X");
+               if (err < 0)
+                       return err;
                break;
        default:
                strcpy(card->mixername, "???");
index b540ad71eb0d733ab217550a66ac40eb35e22da6..6cc3cf2855586901c45962535fec65718ad3139f 100644 (file)
@@ -1367,6 +1367,12 @@ static int azx_first_init(struct azx *chip)
        /* initialize streams */
        azx_init_stream(chip);
 
+       /* workaround for Broadwell HDMI: the first stream is broken,
+        * so mask it by keeping it as if opened
+        */
+       if (pci->vendor == 0x8086 && pci->device == 0x160c)
+               chip->azx_dev[0].opened = 1;
+
        /* initialize chip */
        azx_init_pci(chip);
        azx_init_chip(chip, (probe_only[dev] & 2) == 0);
@@ -1737,6 +1743,9 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
        /* Lynx Point */
        { PCI_DEVICE(0x8086, 0x8c20),
          .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
+       /* 9 Series */
+       { PCI_DEVICE(0x8086, 0x8ca0),
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Wellsburg */
        { PCI_DEVICE(0x8086, 0x8d20),
          .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
index 0cb5b89cd0c8b3e81dd57a0bcdaa471d67d018c1..b4218a19df22209e227538b0056a79cbe1c21279 100644 (file)
@@ -1127,8 +1127,10 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
                                            AMP_OUT_UNMUTE);
 
        eld = &per_pin->sink_eld;
-       if (!eld->monitor_present)
+       if (!eld->monitor_present) {
+               hdmi_set_channel_count(codec, per_pin->cvt_nid, channels);
                return;
+       }
 
        if (!non_pcm && per_pin->chmap_set)
                ca = hdmi_manual_channel_allocation(channels, per_pin->chmap);
@@ -3330,6 +3332,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = {
 { .id = 0x10de0051, .name = "GPU 51 HDMI/DP",  .patch = patch_nvhdmi },
 { .id = 0x10de0060, .name = "GPU 60 HDMI/DP",  .patch = patch_nvhdmi },
 { .id = 0x10de0067, .name = "MCP67 HDMI",      .patch = patch_nvhdmi_2ch },
+{ .id = 0x10de0071, .name = "GPU 71 HDMI/DP",  .patch = patch_nvhdmi },
 { .id = 0x10de8001, .name = "MCP73 HDMI",      .patch = patch_nvhdmi_2ch },
 { .id = 0x11069f80, .name = "VX900 HDMI/DP",   .patch = patch_via_hdmi },
 { .id = 0x11069f81, .name = "VX900 HDMI/DP",   .patch = patch_via_hdmi },
@@ -3385,6 +3388,7 @@ MODULE_ALIAS("snd-hda-codec-id:10de0044");
 MODULE_ALIAS("snd-hda-codec-id:10de0051");
 MODULE_ALIAS("snd-hda-codec-id:10de0060");
 MODULE_ALIAS("snd-hda-codec-id:10de0067");
+MODULE_ALIAS("snd-hda-codec-id:10de0071");
 MODULE_ALIAS("snd-hda-codec-id:10de8001");
 MODULE_ALIAS("snd-hda-codec-id:11069f80");
 MODULE_ALIAS("snd-hda-codec-id:11069f81");
index c1952c9103398953ba0e05078f2f1a21763c8e90..49e884fb3e5db064426758b8c8612a42a1633830 100644 (file)
@@ -4616,13 +4616,17 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0653, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0657, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0658, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x065c, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x065f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0662, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0667, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0668, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0669, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0674, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x067e, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x067f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0680, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1028, 0x0684, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
index fa158cfe9b32d396d09bdb266727c57203c7e62d..d1929de641e24eb4ec733820f8b7dc717d542d33 100644 (file)
@@ -376,7 +376,7 @@ static int aic31xx_dapm_power_event(struct snd_soc_dapm_widget *w,
                reg = AIC31XX_ADCFLAG;
                break;
        default:
-               dev_err(w->codec->dev, "Unknown widget '%s' calling %s/n",
+               dev_err(w->codec->dev, "Unknown widget '%s' calling %s\n",
                        w->name, __func__);
                return -EINVAL;
        }
index 5522d2566c6742d5ee19f91b4358b30f51276b62..ecd26dd2e442fb2e4019eca0238fdb9edba4a73e 100644 (file)
@@ -154,6 +154,7 @@ static struct reg_default wm8962_reg[] = {
        { 40, 0x0000 },   /* R40    - SPKOUTL volume */
        { 41, 0x0000 },   /* R41    - SPKOUTR volume */
 
+       { 49, 0x0010 },   /* R49    - Class D Control 1 */
        { 51, 0x0003 },   /* R51    - Class D Control 2 */
 
        { 56, 0x0506 },   /* R56    - Clocking 4 */
@@ -795,7 +796,6 @@ static bool wm8962_volatile_register(struct device *dev, unsigned int reg)
        case WM8962_ALC2:
        case WM8962_THERMAL_SHUTDOWN_STATUS:
        case WM8962_ADDITIONAL_CONTROL_4:
-       case WM8962_CLASS_D_CONTROL_1:
        case WM8962_DC_SERVO_6:
        case WM8962_INTERRUPT_STATUS_1:
        case WM8962_INTERRUPT_STATUS_2:
@@ -2929,13 +2929,22 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
 static int wm8962_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
-       int val;
+       int val, ret;
 
        if (mute)
-               val = WM8962_DAC_MUTE;
+               val = WM8962_DAC_MUTE | WM8962_DAC_MUTE_ALT;
        else
                val = 0;
 
+       /**
+        * The DAC mute bit is mirrored in two registers, update both to keep
+        * the register cache consistent.
+        */
+       ret = snd_soc_update_bits(codec, WM8962_CLASS_D_CONTROL_1,
+                                 WM8962_DAC_MUTE_ALT, val);
+       if (ret < 0)
+               return ret;
+
        return snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1,
                                   WM8962_DAC_MUTE, val);
 }
index a1a5d5294c19dea3d76ce03be2dfe490d925bd78..910aafd09d21e210d2b6e0b36c7e3243533d5e6b 100644 (file)
 #define WM8962_SPKOUTL_ENA_MASK                 0x0040  /* SPKOUTL_ENA */
 #define WM8962_SPKOUTL_ENA_SHIFT                     6  /* SPKOUTL_ENA */
 #define WM8962_SPKOUTL_ENA_WIDTH                     1  /* SPKOUTL_ENA */
+#define WM8962_DAC_MUTE_ALT                     0x0010  /* DAC_MUTE */
+#define WM8962_DAC_MUTE_ALT_MASK                0x0010  /* DAC_MUTE */
+#define WM8962_DAC_MUTE_ALT_SHIFT                    4  /* DAC_MUTE */
+#define WM8962_DAC_MUTE_ALT_WIDTH                    1  /* DAC_MUTE */
 #define WM8962_SPKOUTL_PGA_MUTE                 0x0002  /* SPKOUTL_PGA_MUTE */
 #define WM8962_SPKOUTL_PGA_MUTE_MASK            0x0002  /* SPKOUTL_PGA_MUTE */
 #define WM8962_SPKOUTL_PGA_MUTE_SHIFT                1  /* SPKOUTL_PGA_MUTE */
index c8e5db1414d7e75f4077728765a210877f4b3cd9..496ce2eb2f1f31f4c4f0b6776ffd4d9a60243992 100644 (file)
@@ -258,10 +258,16 @@ static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
                return -EINVAL;
        }
 
-       if (ratio == 1) {
+       /* Only EXTAL source can be output directly without using PSR and PM */
+       if (ratio == 1 && clksrc == esai_priv->extalclk) {
                /* Bypass all the dividers if not being needed */
                ecr |= tx ? ESAI_ECR_ETO : ESAI_ECR_ERO;
                goto out;
+       } else if (ratio < 2) {
+               /* The ratio should be no less than 2 if using other sources */
+               dev_err(dai->dev, "failed to derive required HCK%c rate\n",
+                               tx ? 'T' : 'R');
+               return -EINVAL;
        }
 
        ret = fsl_esai_divisor_cal(dai, tx, ratio, false, 0);
@@ -307,7 +313,8 @@ static int fsl_esai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
                return -EINVAL;
        }
 
-       if (esai_priv->sck_div[tx] && (ratio > 16 || ratio == 0)) {
+       /* The ratio should be contented by FP alone if bypassing PM and PSR */
+       if (!esai_priv->sck_div[tx] && (ratio > 16 || ratio == 0)) {
                dev_err(dai->dev, "the ratio is out of range (1 ~ 16)\n");
                return -EINVAL;
        }
@@ -454,12 +461,6 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream,
        }
 
        if (!dai->active) {
-               /* Reset Port C */
-               regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
-                                  ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO));
-               regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
-                                  ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO));
-
                /* Set synchronous mode */
                regmap_update_bits(esai_priv->regmap, REG_ESAI_SAICR,
                                   ESAI_SAICR_SYNC, esai_priv->synchronous ?
@@ -519,6 +520,11 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
 
        regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), mask, val);
 
+       /* Remove ESAI personal reset by configuring ESAI_PCRC and ESAI_PRRC */
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
+                          ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO));
+       regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC,
+                          ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO));
        return 0;
 }
 
index ac869931d7f16c9c4049aefaffb4a7d416417e49..267717aa96c14e971329cfe2f728d1f141de72c3 100644 (file)
@@ -145,7 +145,7 @@ static const struct file_operations audmux_debugfs_fops = {
        .llseek = default_llseek,
 };
 
-static void __init audmux_debugfs_init(void)
+static void audmux_debugfs_init(void)
 {
        int i;
        char buf[20];
index 5d06eecb61986da272fcda4858db56c91d285153..18aee77f8d4a55276194542c41464feb363784d3 100644 (file)
@@ -138,6 +138,7 @@ static int sst_acpi_probe(struct platform_device *pdev)
 
        sst_pdata = &sst_acpi->sst_pdata;
        sst_pdata->id = desc->sst_id;
+       sst_pdata->dma_dev = dev;
        sst_acpi->desc = desc;
        sst_acpi->mach = mach;
 
index a50bf7fc0e3abf8dc729e7ce77f75ef40848480e..adf0aca5aca60423d2643a81679ce291f44d1208 100644 (file)
@@ -324,7 +324,7 @@ static int sst_byt_init(struct sst_dsp *sst, struct sst_pdata *pdata)
        memcpy_toio(sst->addr.lpe + SST_BYT_MAILBOX_OFFSET,
               &pdata->fw_base, sizeof(u32));
 
-       ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
+       ret = dma_coerce_mask_and_coherent(sst->dma_dev, DMA_BIT_MASK(32));
        if (ret)
                return ret;
 
index d0eaeee21be4c634ae88e984cf964c5067b5cae6..0d31dbbf480652e773243dca639f042a4c531bc0 100644 (file)
@@ -542,16 +542,20 @@ struct sst_byt_stream *sst_byt_stream_new(struct sst_byt *byt, int id,
        void *data)
 {
        struct sst_byt_stream *stream;
+       struct sst_dsp *sst = byt->dsp;
+       unsigned long flags;
 
        stream = kzalloc(sizeof(*stream), GFP_KERNEL);
        if (stream == NULL)
                return NULL;
 
+       spin_lock_irqsave(&sst->spinlock, flags);
        list_add(&stream->node, &byt->stream_list);
        stream->notify_position = notify_position;
        stream->pdata = data;
        stream->byt = byt;
        stream->str_id = id;
+       spin_unlock_irqrestore(&sst->spinlock, flags);
 
        return stream;
 }
@@ -630,6 +634,8 @@ int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream)
 {
        u64 header;
        int ret = 0;
+       struct sst_dsp *sst = byt->dsp;
+       unsigned long flags;
 
        if (!stream->commited)
                goto out;
@@ -644,8 +650,10 @@ int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream)
 
        stream->commited = false;
 out:
+       spin_lock_irqsave(&sst->spinlock, flags);
        list_del(&stream->node);
        kfree(stream);
+       spin_unlock_irqrestore(&sst->spinlock, flags);
 
        return ret;
 }
index 30ca14a6a83595d5acf4e644d7f8d50827a99a98..401213455497258111dcf939c7d963fbbbeb3e37 100644 (file)
@@ -228,6 +228,7 @@ struct sst_dsp {
        spinlock_t spinlock;    /* IPC locking */
        struct mutex mutex;     /* DSP FW lock */
        struct device *dev;
+       struct device *dma_dev;
        void *thread_context;
        int irq;
        u32 id;
index 0c129fd85ecf8a37b3758dfc924a9e5091c9e01e..0b715b20a2d7d46b9f06189de1ee57d9aacc28ab 100644 (file)
@@ -337,6 +337,7 @@ struct sst_dsp *sst_dsp_new(struct device *dev,
        spin_lock_init(&sst->spinlock);
        mutex_init(&sst->mutex);
        sst->dev = dev;
+       sst->dma_dev = pdata->dma_dev;
        sst->thread_context = sst_dev->thread_context;
        sst->sst_dev = sst_dev;
        sst->id = pdata->id;
index 74052b59485ca1ce942444d0a3871ed8a6051672..e44423be66c459ba721249d0efe21bccdaeea4b5 100644 (file)
@@ -169,6 +169,7 @@ struct sst_pdata {
        u32 dma_base;
        u32 dma_size;
        int dma_engine;
+       struct device *dma_dev;
 
        /* DSP */
        u32 id;
index f7687107cf7f51f19a95992b79819270e3dd4734..928f228c38e754db3f41551208493045ce9ee561 100644 (file)
@@ -57,14 +57,8 @@ struct sst_fw *sst_fw_new(struct sst_dsp *dsp,
        sst_fw->private = private;
        sst_fw->size = fw->size;
 
-       err = dma_coerce_mask_and_coherent(dsp->dev, DMA_BIT_MASK(32));
-       if (err < 0) {
-               kfree(sst_fw);
-               return NULL;
-       }
-
        /* allocate DMA buffer to store FW data */
-       sst_fw->dma_buf = dma_alloc_coherent(dsp->dev, sst_fw->size,
+       sst_fw->dma_buf = dma_alloc_coherent(dsp->dma_dev, sst_fw->size,
                                &sst_fw->dmable_fw_paddr, GFP_DMA | GFP_KERNEL);
        if (!sst_fw->dma_buf) {
                dev_err(dsp->dev, "error: DMA alloc failed\n");
@@ -106,7 +100,7 @@ void sst_fw_free(struct sst_fw *sst_fw)
        list_del(&sst_fw->list);
        mutex_unlock(&dsp->mutex);
 
-       dma_free_coherent(dsp->dev, sst_fw->size, sst_fw->dma_buf,
+       dma_free_coherent(dsp->dma_dev, sst_fw->size, sst_fw->dma_buf,
                        sst_fw->dmable_fw_paddr);
        kfree(sst_fw);
 }
@@ -202,6 +196,9 @@ static int block_alloc_contiguous(struct sst_module *module,
                size -= block->size;
        }
 
+       list_for_each_entry(block, &tmp, list)
+               list_add(&block->module_list, &module->block_list);
+
        list_splice(&tmp, &dsp->used_block_list);
        return 0;
 }
@@ -247,8 +244,7 @@ static int block_alloc(struct sst_module *module,
                /* do we span > 1 blocks */
                if (data->size > block->size) {
                        ret = block_alloc_contiguous(module, data,
-                               block->offset + block->size,
-                               data->size - block->size);
+                               block->offset, data->size);
                        if (ret == 0)
                                return ret;
                }
@@ -344,7 +340,7 @@ static int block_alloc_fixed(struct sst_module *module,
 
                        err = block_alloc_contiguous(module, data,
                                block->offset + block->size,
-                               data->size - block->size + data->offset - block->offset);
+                               data->size - block->size);
                        if (err < 0)
                                return -ENOMEM;
 
@@ -371,15 +367,10 @@ static int block_alloc_fixed(struct sst_module *module,
                if (data->offset >= block->offset && data->offset < block_end) {
 
                        err = block_alloc_contiguous(module, data,
-                               block->offset + block->size,
-                               data->size - block->size);
+                               block->offset, data->size);
                        if (err < 0)
                                return -ENOMEM;
 
-                       /* add block */
-                       block->data_type = data->data_type;
-                       list_move(&block->list, &dsp->used_block_list);
-                       list_add(&block->module_list, &module->block_list);
                        return 0;
                }
 
index f5ebf36af8898d8a94d4a46886bfcfe0964d0567..535f517629fd608fb7c4bd3eb79a05a67d98a518 100644 (file)
@@ -433,7 +433,7 @@ static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata)
        int ret = -ENODEV, i, j, region_count;
        u32 offset, size;
 
-       dev = sst->dev;
+       dev = sst->dma_dev;
 
        switch (sst->id) {
        case SST_DEV_ID_LYNX_POINT:
@@ -466,7 +466,7 @@ static int hsw_init(struct sst_dsp *sst, struct sst_pdata *pdata)
                return ret;
        }
 
-       ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
+       ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(31));
        if (ret)
                return ret;
 
index 50e4246d4b57a2df8c9ad0c54deabb4e346ca572..e7996b39a48480a8577ac26d6cad28e3392259aa 100644 (file)
@@ -1159,11 +1159,14 @@ struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id,
        void *data)
 {
        struct sst_hsw_stream *stream;
+       struct sst_dsp *sst = hsw->dsp;
+       unsigned long flags;
 
        stream = kzalloc(sizeof(*stream), GFP_KERNEL);
        if (stream == NULL)
                return NULL;
 
+       spin_lock_irqsave(&sst->spinlock, flags);
        list_add(&stream->node, &hsw->stream_list);
        stream->notify_position = notify_position;
        stream->pdata = data;
@@ -1172,6 +1175,7 @@ struct sst_hsw_stream *sst_hsw_stream_new(struct sst_hsw *hsw, int id,
 
        /* work to process notification messages */
        INIT_WORK(&stream->notify_work, hsw_notification_work);
+       spin_unlock_irqrestore(&sst->spinlock, flags);
 
        return stream;
 }
@@ -1180,6 +1184,8 @@ int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream)
 {
        u32 header;
        int ret = 0;
+       struct sst_dsp *sst = hsw->dsp;
+       unsigned long flags;
 
        /* dont free DSP streams that are not commited */
        if (!stream->commited)
@@ -1201,8 +1207,11 @@ int sst_hsw_stream_free(struct sst_hsw *hsw, struct sst_hsw_stream *stream)
        trace_hsw_stream_free_req(stream, &stream->free_req);
 
 out:
+       cancel_work_sync(&stream->notify_work);
+       spin_lock_irqsave(&sst->spinlock, flags);
        list_del(&stream->node);
        kfree(stream);
+       spin_unlock_irqrestore(&sst->spinlock, flags);
 
        return ret;
 }
@@ -1538,10 +1547,28 @@ int sst_hsw_stream_reset(struct sst_hsw *hsw, struct sst_hsw_stream *stream)
 }
 
 /* Stream pointer positions */
-int sst_hsw_get_dsp_position(struct sst_hsw *hsw,
+u32 sst_hsw_get_dsp_position(struct sst_hsw *hsw,
        struct sst_hsw_stream *stream)
 {
-       return stream->rpos.position;
+       u32 rpos;
+
+       sst_dsp_read(hsw->dsp, &rpos,
+               stream->reply.read_position_register_address, sizeof(rpos));
+
+       return rpos;
+}
+
+/* Stream presentation (monotonic) positions */
+u64 sst_hsw_get_dsp_presentation_position(struct sst_hsw *hsw,
+       struct sst_hsw_stream *stream)
+{
+       u64 ppos;
+
+       sst_dsp_read(hsw->dsp, &ppos,
+               stream->reply.presentation_position_register_address,
+               sizeof(ppos));
+
+       return ppos;
 }
 
 int sst_hsw_stream_set_write_position(struct sst_hsw *hsw,
index d517929ccc389e2aaca3321106b6088250929482..2ac194a6d04b226eb86cb42c2361c643f7400635 100644 (file)
@@ -464,7 +464,9 @@ int sst_hsw_stream_get_write_pos(struct sst_hsw *hsw,
        struct sst_hsw_stream *stream, u32 *position);
 int sst_hsw_stream_set_write_position(struct sst_hsw *hsw,
        struct sst_hsw_stream *stream, u32 stage_id, u32 position);
-int sst_hsw_get_dsp_position(struct sst_hsw *hsw,
+u32 sst_hsw_get_dsp_position(struct sst_hsw *hsw,
+       struct sst_hsw_stream *stream);
+u64 sst_hsw_get_dsp_presentation_position(struct sst_hsw *hsw,
        struct sst_hsw_stream *stream);
 
 /* HW port config */
index 0a32dd13a23d28ab96282b75592c20d5b133ee9f..9d5f64a583a388bd501973c32ae3d5d086d6acc6 100644 (file)
@@ -99,6 +99,7 @@ struct hsw_pcm_data {
        struct snd_compr_stream *cstream;
        unsigned int wpos;
        struct mutex mutex;
+       bool allocated;
 };
 
 /* private data for the driver */
@@ -107,12 +108,14 @@ struct hsw_priv_data {
        struct sst_hsw *hsw;
 
        /* page tables */
-       unsigned char *pcm_pg[HSW_PCM_COUNT][2];
+       struct snd_dma_buffer dmab[HSW_PCM_COUNT][2];
 
        /* DAI data */
        struct hsw_pcm_data pcm[HSW_PCM_COUNT];
 };
 
+static u32 hsw_notify_pointer(struct sst_hsw_stream *stream, void *data);
+
 static inline u32 hsw_mixer_to_ipc(unsigned int value)
 {
        if (value >= ARRAY_SIZE(volume_map))
@@ -273,28 +276,26 @@ static const struct snd_kcontrol_new hsw_volume_controls[] = {
 };
 
 /* Create DMA buffer page table for DSP */
-static int create_adsp_page_table(struct hsw_priv_data *pdata,
-       struct snd_soc_pcm_runtime *rtd,
-       unsigned char *dma_area, size_t size, int pcm, int stream)
+static int create_adsp_page_table(struct snd_pcm_substream *substream,
+       struct hsw_priv_data *pdata, struct snd_soc_pcm_runtime *rtd,
+       unsigned char *dma_area, size_t size, int pcm)
 {
-       int i, pages;
+       struct snd_dma_buffer *dmab = snd_pcm_get_dma_buf(substream);
+       int i, pages, stream = substream->stream;
 
-       if (size % PAGE_SIZE)
-               pages = (size / PAGE_SIZE) + 1;
-       else
-               pages = size / PAGE_SIZE;
+       pages = snd_sgbuf_aligned_pages(size);
 
        dev_dbg(rtd->dev, "generating page table for %p size 0x%zu pages %d\n",
                dma_area, size, pages);
 
        for (i = 0; i < pages; i++) {
                u32 idx = (((i << 2) + i)) >> 1;
-               u32 pfn = (virt_to_phys(dma_area + i * PAGE_SIZE)) >> PAGE_SHIFT;
+               u32 pfn = snd_sgbuf_get_addr(dmab, i * PAGE_SIZE) >> PAGE_SHIFT;
                u32 *pg_table;
 
                dev_dbg(rtd->dev, "pfn i %i idx %d pfn %x\n", i, idx, pfn);
 
-               pg_table = (u32*)(pdata->pcm_pg[pcm][stream] + idx);
+               pg_table = (u32 *)(pdata->dmab[pcm][stream].area + idx);
 
                if (i & 1)
                        *pg_table |= (pfn << 4);
@@ -317,12 +318,36 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream,
        struct sst_hsw *hsw = pdata->hsw;
        struct sst_module *module_data;
        struct sst_dsp *dsp;
+       struct snd_dma_buffer *dmab;
        enum sst_hsw_stream_type stream_type;
        enum sst_hsw_stream_path_id path_id;
        u32 rate, bits, map, pages, module_id;
        u8 channels;
        int ret;
 
+       /* check if we are being called a subsequent time */
+       if (pcm_data->allocated) {
+               ret = sst_hsw_stream_reset(hsw, pcm_data->stream);
+               if (ret < 0)
+                       dev_dbg(rtd->dev, "error: reset stream failed %d\n",
+                               ret);
+
+               ret = sst_hsw_stream_free(hsw, pcm_data->stream);
+               if (ret < 0) {
+                       dev_dbg(rtd->dev, "error: free stream failed %d\n",
+                               ret);
+                       return ret;
+               }
+               pcm_data->allocated = false;
+
+               pcm_data->stream = sst_hsw_stream_new(hsw, rtd->cpu_dai->id,
+                       hsw_notify_pointer, pcm_data);
+               if (pcm_data->stream == NULL) {
+                       dev_err(rtd->dev, "error: failed to create stream\n");
+                       return -EINVAL;
+               }
+       }
+
        /* stream direction */
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                path_id = SST_HSW_STREAM_PATH_SSP0_OUT;
@@ -416,8 +441,10 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream,
                return ret;
        }
 
-       ret = create_adsp_page_table(pdata, rtd, runtime->dma_area,
-               runtime->dma_bytes, rtd->cpu_dai->id, substream->stream);
+       dmab = snd_pcm_get_dma_buf(substream);
+
+       ret = create_adsp_page_table(substream, pdata, rtd, runtime->dma_area,
+               runtime->dma_bytes, rtd->cpu_dai->id);
        if (ret < 0)
                return ret;
 
@@ -430,9 +457,9 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream,
                pages = runtime->dma_bytes / PAGE_SIZE;
 
        ret = sst_hsw_stream_buffer(hsw, pcm_data->stream,
-               virt_to_phys(pdata->pcm_pg[rtd->cpu_dai->id][substream->stream]),
+               pdata->dmab[rtd->cpu_dai->id][substream->stream].addr,
                pages, runtime->dma_bytes, 0,
-               (u32)(virt_to_phys(runtime->dma_area) >> PAGE_SHIFT));
+               snd_sgbuf_get_addr(dmab, 0) >> PAGE_SHIFT);
        if (ret < 0) {
                dev_err(rtd->dev, "error: failed to set DMA buffer %d\n", ret);
                return ret;
@@ -474,6 +501,7 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream,
                dev_err(rtd->dev, "error: failed to commit stream %d\n", ret);
                return ret;
        }
+       pcm_data->allocated = true;
 
        ret = sst_hsw_stream_pause(hsw, pcm_data->stream, 1);
        if (ret < 0)
@@ -541,12 +569,14 @@ static snd_pcm_uframes_t hsw_pcm_pointer(struct snd_pcm_substream *substream)
        struct hsw_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd);
        struct sst_hsw *hsw = pdata->hsw;
        snd_pcm_uframes_t offset;
+       uint64_t ppos;
+       u32 position = sst_hsw_get_dsp_position(hsw, pcm_data->stream);
 
-       offset = bytes_to_frames(runtime,
-               sst_hsw_get_dsp_position(hsw, pcm_data->stream));
+       offset = bytes_to_frames(runtime, position);
+       ppos = sst_hsw_get_dsp_presentation_position(hsw, pcm_data->stream);
 
-       dev_dbg(rtd->dev, "PCM: DMA pointer %zu bytes\n",
-               frames_to_bytes(runtime, (u32)offset));
+       dev_dbg(rtd->dev, "PCM: DMA pointer %du bytes, pos %llu\n",
+               position, ppos);
        return offset;
 }
 
@@ -606,6 +636,7 @@ static int hsw_pcm_close(struct snd_pcm_substream *substream)
                dev_dbg(rtd->dev, "error: free stream failed %d\n", ret);
                goto out;
        }
+       pcm_data->allocated = 0;
        pcm_data->stream = NULL;
 
 out:
@@ -621,7 +652,7 @@ static struct snd_pcm_ops hsw_pcm_ops = {
        .hw_free        = hsw_pcm_hw_free,
        .trigger        = hsw_pcm_trigger,
        .pointer        = hsw_pcm_pointer,
-       .mmap           = snd_pcm_lib_default_mmap,
+       .page           = snd_pcm_sgbuf_ops_page,
 };
 
 static void hsw_pcm_free(struct snd_pcm *pcm)
@@ -632,17 +663,16 @@ static void hsw_pcm_free(struct snd_pcm *pcm)
 static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_pcm *pcm = rtd->pcm;
+       struct snd_soc_platform *platform = rtd->platform;
+       struct sst_pdata *pdata = dev_get_platdata(platform->dev);
+       struct device *dev = pdata->dma_dev;
        int ret = 0;
 
-       ret = dma_coerce_mask_and_coherent(rtd->card->dev, DMA_BIT_MASK(32));
-       if (ret)
-               return ret;
-
        if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream ||
                        pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
                ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
-                       SNDRV_DMA_TYPE_DEV,
-                       rtd->card->dev,
+                       SNDRV_DMA_TYPE_DEV_SG,
+                       dev,
                        hsw_pcm_hardware.buffer_bytes_max,
                        hsw_pcm_hardware.buffer_bytes_max);
                if (ret) {
@@ -742,11 +772,14 @@ static int hsw_pcm_probe(struct snd_soc_platform *platform)
 {
        struct sst_pdata *pdata = dev_get_platdata(platform->dev);
        struct hsw_priv_data *priv_data;
-       int i;
+       struct device *dma_dev;
+       int i, ret = 0;
 
        if (!pdata)
                return -ENODEV;
 
+       dma_dev = pdata->dma_dev;
+
        priv_data = devm_kzalloc(platform->dev, sizeof(*priv_data), GFP_KERNEL);
        priv_data->hsw = pdata->dsp;
        snd_soc_platform_set_drvdata(platform, priv_data);
@@ -758,15 +791,17 @@ static int hsw_pcm_probe(struct snd_soc_platform *platform)
 
                /* playback */
                if (hsw_dais[i].playback.channels_min) {
-                       priv_data->pcm_pg[i][0] = kzalloc(PAGE_SIZE, GFP_DMA);
-                       if (priv_data->pcm_pg[i][0] == NULL)
+                       ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dma_dev,
+                               PAGE_SIZE, &priv_data->dmab[i][0]);
+                       if (ret < 0)
                                goto err;
                }
 
                /* capture */
                if (hsw_dais[i].capture.channels_min) {
-                       priv_data->pcm_pg[i][1] = kzalloc(PAGE_SIZE, GFP_DMA);
-                       if (priv_data->pcm_pg[i][1] == NULL)
+                       ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dma_dev,
+                               PAGE_SIZE, &priv_data->dmab[i][1]);
+                       if (ret < 0)
                                goto err;
                }
        }
@@ -776,11 +811,11 @@ static int hsw_pcm_probe(struct snd_soc_platform *platform)
 err:
        for (;i >= 0; i--) {
                if (hsw_dais[i].playback.channels_min)
-                       kfree(priv_data->pcm_pg[i][0]);
+                       snd_dma_free_pages(&priv_data->dmab[i][0]);
                if (hsw_dais[i].capture.channels_min)
-                       kfree(priv_data->pcm_pg[i][1]);
+                       snd_dma_free_pages(&priv_data->dmab[i][1]);
        }
-       return -ENOMEM;
+       return ret;
 }
 
 static int hsw_pcm_remove(struct snd_soc_platform *platform)
@@ -791,9 +826,9 @@ static int hsw_pcm_remove(struct snd_soc_platform *platform)
 
        for (i = 0; i < ARRAY_SIZE(hsw_dais); i++) {
                if (hsw_dais[i].playback.channels_min)
-                       kfree(priv_data->pcm_pg[i][0]);
+                       snd_dma_free_pages(&priv_data->dmab[i][0]);
                if (hsw_dais[i].capture.channels_min)
-                       kfree(priv_data->pcm_pg[i][1]);
+                       snd_dma_free_pages(&priv_data->dmab[i][1]);
        }
 
        return 0;
index 215b668166be6c50d01963cac2ef62598cf6f7b2..89424470a1f3860eab989eabeab579184e070359 100644 (file)
@@ -197,13 +197,12 @@ static void rsnd_dma_complete(void *data)
         * rsnd_dai_pointer_update() will be called twice,
         * ant it will breaks io->byte_pos
         */
-
-       rsnd_dai_pointer_update(io, io->byte_per_period);
-
        if (dma->submit_loop)
                rsnd_dma_continue(dma);
 
        rsnd_unlock(priv, flags);
+
+       rsnd_dai_pointer_update(io, io->byte_per_period);
 }
 
 static void __rsnd_dma_start(struct rsnd_dma *dma)
index 7769b0a2bc5a5287f932d20524216f7c390fd4c7..6d6ceee447d559e711ba8eccc2e734953585d9ad 100644 (file)
@@ -1612,8 +1612,11 @@ static void dapm_pre_sequence_async(void *data, async_cookie_t cookie)
                                "ASoC: Failed to turn on bias: %d\n", ret);
        }
 
-       /* Prepare for a STADDBY->ON or ON->STANDBY transition */
-       if (d->bias_level != d->target_bias_level) {
+       /* Prepare for a transition to ON or away from ON */
+       if ((d->target_bias_level == SND_SOC_BIAS_ON &&
+            d->bias_level != SND_SOC_BIAS_ON) ||
+           (d->target_bias_level != SND_SOC_BIAS_ON &&
+            d->bias_level == SND_SOC_BIAS_ON)) {
                ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_PREPARE);
                if (ret != 0)
                        dev_err(d->dev,
@@ -3475,8 +3478,11 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
                cpu_dai = rtd->cpu_dai;
                codec_dai = rtd->codec_dai;
 
-               /* dynamic FE links have no fixed DAI mapping */
-               if (rtd->dai_link->dynamic)
+               /*
+                * dynamic FE links have no fixed DAI mapping.
+                * CODEC<->CODEC links have no direct connection.
+                */
+               if (rtd->dai_link->dynamic || rtd->dai_link->params)
                        continue;
 
                /* there is no point in connecting BE DAI links with dummies */
index 2cedf09f6d9613c7b34bb22888806fde598052c6..a391de05803765403fc94e989717ad7dae91db5c 100644 (file)
@@ -1675,7 +1675,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream,
                        be->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
                        break;
                case SNDRV_PCM_TRIGGER_SUSPEND:
-                       if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP)
+                       if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
                                continue;
 
                        if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
index 893d5a1afc3ce6bf854a61ef0c3f4f54cc552d0d..c3b5b7dca1c3a8fd4b771512c841bb32e27b5554 100644 (file)
@@ -651,7 +651,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)
        int err = -ENODEV;
 
        down_read(&chip->shutdown_rwsem);
-       if (chip->probing)
+       if (chip->probing && chip->in_pm)
                err = 0;
        else if (!chip->shutdown)
                err = usb_autopm_get_interface(chip->pm_intf);
@@ -663,7 +663,7 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)
 void snd_usb_autosuspend(struct snd_usb_audio *chip)
 {
        down_read(&chip->shutdown_rwsem);
-       if (!chip->shutdown && !chip->probing)
+       if (!chip->shutdown && !chip->probing && !chip->in_pm)
                usb_autopm_put_interface(chip->pm_intf);
        up_read(&chip->shutdown_rwsem);
 }
@@ -695,8 +695,9 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
                        chip->autosuspended = 1;
        }
 
-       list_for_each_entry(mixer, &chip->mixer_list, list)
-               snd_usb_mixer_suspend(mixer);
+       if (chip->num_suspended_intf == 1)
+               list_for_each_entry(mixer, &chip->mixer_list, list)
+                       snd_usb_mixer_suspend(mixer);
 
        return 0;
 }
@@ -711,6 +712,8 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
                return 0;
        if (--chip->num_suspended_intf)
                return 0;
+
+       chip->in_pm = 1;
        /*
         * ALSA leaves material resumption to user space
         * we just notify and restart the mixers
@@ -726,6 +729,7 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume)
        chip->autosuspended = 0;
 
 err_out:
+       chip->in_pm = 0;
        return err;
 }
 
index 9867ab866857260df9432b4378d5ba87c1d90834..97acb906acc27041cebb340abaa9d69c36c34634 100644 (file)
@@ -92,6 +92,7 @@ struct snd_usb_endpoint {
        unsigned int curframesize;      /* current packet size in frames (for capture) */
        unsigned int syncmaxsize;       /* sync endpoint packet size */
        unsigned int fill_max:1;        /* fill max packet size always */
+       unsigned int udh01_fb_quirk:1;  /* corrupted feedback data */
        unsigned int datainterval;      /* log_2 of data packet interval */
        unsigned int syncinterval;      /* P for adaptive mode, 0 otherwise */
        unsigned char silence_value;
index e70a87e0d9fe6402765afa0741b9f974b1259bec..289f582c91303cd6bd26d194124b36702f8e4915 100644 (file)
@@ -471,6 +471,10 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
                        ep->syncinterval = 3;
 
                ep->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize);
+
+               if (chip->usb_id == USB_ID(0x0644, 0x8038) /* TEAC UD-H01 */ &&
+                   ep->syncmaxsize == 4)
+                       ep->udh01_fb_quirk = 1;
        }
 
        list_add_tail(&ep->list, &chip->ep_list);
@@ -1105,7 +1109,16 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
        if (f == 0)
                return;
 
-       if (unlikely(ep->freqshift == INT_MIN)) {
+       if (unlikely(sender->udh01_fb_quirk)) {
+               /*
+                * The TEAC UD-H01 firmware sometimes changes the feedback value
+                * by +/- 0x1.0000.
+                */
+               if (f < ep->freqn - 0x8000)
+                       f += 0x10000;
+               else if (f > ep->freqn + 0x8000)
+                       f -= 0x10000;
+       } else if (unlikely(ep->freqshift == INT_MIN)) {
                /*
                 * The first time we see a feedback value, determine its format
                 * by shifting it left or right until it matches the nominal
index 131336d40492786b2283df01577a1957b0556a66..c62a1659106d2c3da63152d59e1302e2eee47d6d 100644 (file)
@@ -1501,9 +1501,8 @@ static void retire_playback_urb(struct snd_usb_substream *subs,
         * The error should be lower than 2ms since the estimate relies
         * on two reads of a counter updated every ms.
         */
-       if (printk_ratelimit() &&
-           abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2)
-               dev_dbg(&subs->dev->dev,
+       if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2)
+               dev_dbg_ratelimited(&subs->dev->dev,
                        "delay: estimated %d, actual %d\n",
                        est_delay, subs->last_delay);
 
index 25c4c7e217de603c1f02c5c714833e6f29d92c3b..91d0380431b4f79f1e209cd973b7f44152caa494 100644 (file)
@@ -40,6 +40,7 @@ struct snd_usb_audio {
        struct rw_semaphore shutdown_rwsem;
        unsigned int shutdown:1;
        unsigned int probing:1;
+       unsigned int in_pm:1;
        unsigned int autosuspended:1;   
        unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */
        
index bcae806b0c398d5450975ab08001e7a808e376c4..9a617adc6675dc06552de428c93b3c611599900b 100644 (file)
@@ -44,6 +44,9 @@ cpupower: FORCE
 cgroup firewire hv guest usb virtio vm net: FORCE
        $(call descend,$@)
 
+liblockdep: FORCE
+       $(call descend,lib/lockdep)
+
 libapikfs: FORCE
        $(call descend,lib/api)
 
@@ -91,6 +94,9 @@ cpupower_clean:
 cgroup_clean hv_clean firewire_clean lguest_clean usb_clean virtio_clean vm_clean net_clean:
        $(call descend,$(@:_clean=),clean)
 
+liblockdep_clean:
+       $(call descend,lib/lockdep,clean)
+
 libapikfs_clean:
        $(call descend,lib/api,clean)
 
index cb09d3ff8f5856dab489130133ec9c2e2ba73db8..bba2f5253b6e281ff85abdf65a76406d88d6503b 100644 (file)
@@ -1,8 +1,7 @@
 # file format version
 FILE_VERSION = 1
 
-MAKEFLAGS += --no-print-directory
-LIBLOCKDEP_VERSION=$(shell make -sC ../../.. kernelversion)
+LIBLOCKDEP_VERSION=$(shell make --no-print-directory -sC ../../.. kernelversion)
 
 # Makefiles suck: This macro sets a default value of $(2) for the
 # variable named by $(1), unless the variable has been set by
@@ -231,7 +230,7 @@ install_lib: all_cmd
 install: install_lib
 
 clean:
-       $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d
+       $(RM) *.o *~ $(TARGETS) *.a *liblockdep*.so* $(VERSION_FILES) .*.d
        $(RM) tags TAGS
 
 endif # skip-makefile
index bb31813e43ddca8bd2bad4544e593d8c6df418f2..9a287bec695a3630bc43f19e3376d8cff36d2856 100644 (file)
@@ -820,7 +820,7 @@ do_div:
                r->A &= r->X;
                break;
        case BPF_ALU_AND | BPF_K:
-               r->A &= r->X;
+               r->A &= K;
                break;
        case BPF_ALU_OR | BPF_X:
                r->A |= r->X;