Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 7 Jun 2014 22:01:39 +0000 (15:01 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 7 Jun 2014 22:01:39 +0000 (15:01 -0700)
Pull SCSI target fixes from Nicholas Bellinger:
 "Here are the remaining fixes for v3.15.

  This series includes:

   - iser-target fix for ImmediateData exception reference count bug
     (Sagi + nab)
   - iscsi-target fix for MC/S login + potential iser-target MRDSL
     buffer overrun (Santosh + Roland)
   - iser-target fix for v3.15-rc multi network portal shutdown
     regression (nab)
   - target fix for allowing READ_CAPCITY during ALUA Standby access
     state (Chris + nab)
   - target fix for NULL pointer dereference of alua_access_state for
     un-configured devices (Chris + nab)"

* git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending:
  target: Fix alua_access_state attribute OOPs for un-configured devices
  target: Allow READ_CAPACITY opcode in ALUA Standby access state
  iser-target: Fix multi network portal shutdown regression
  iscsi-target: Fix wrong buffer / buffer overrun in iscsi_change_param_value()
  iser-target: Add missing target_put_sess_cmd for ImmedateData failure

997 files changed:
Documentation/ABI/testing/sysfs-bus-pci
Documentation/DocBook/drm.tmpl
Documentation/DocBook/media/Makefile
Documentation/debugging-via-ohci1394.txt
Documentation/device-mapper/thin-provisioning.txt
Documentation/devicetree/bindings/arm/arch_timer.txt
Documentation/devicetree/bindings/ata/apm-xgene.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/net/arc_emac.txt
Documentation/devicetree/bindings/net/mdio-gpio.txt
Documentation/devicetree/bindings/net/socfpga-dwmac.txt
Documentation/devicetree/bindings/net/stmmac.txt
Documentation/devicetree/bindings/pinctrl/pinctrl-st.txt
Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
Documentation/devicetree/bindings/sound/tlv320aic31xx.txt
Documentation/email-clients.txt
Documentation/filesystems/proc.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/arc/kernel/entry.S
arch/arm/boot/dts/am33xx.dtsi
arch/arm/boot/dts/am3517.dtsi
arch/arm/boot/dts/am4372.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/stih415-pinctrl.dtsi
arch/arm/boot/dts/stih416-pinctrl.dtsi
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/page.h
arch/arm/kernel/entry-header.S
arch/arm/kernel/unwind.c
arch/arm/kvm/Kconfig
arch/arm/kvm/mmu.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/arm64/boot/dts/apm-storm.dtsi
arch/arm64/include/asm/memory.h
arch/arm64/include/asm/pgtable.h
arch/arm64/kernel/early_printk.c
arch/arm64/kernel/irq.c
arch/arm64/kernel/setup.c
arch/arm64/mm/dma-mapping.c
arch/arm64/mm/hugetlbpage.c
arch/arm64/mm/mmu.c
arch/hexagon/include/asm/barrier.h [deleted file]
arch/ia64/include/asm/unistd.h
arch/ia64/include/uapi/asm/unistd.h
arch/ia64/kernel/entry.S
arch/m68k/include/asm/unistd.h
arch/m68k/include/uapi/asm/unistd.h
arch/m68k/kernel/syscalltable.S
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/Kbuild
arch/parisc/include/uapi/asm/resource.h [deleted file]
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/boot/main.c
arch/powerpc/boot/ops.h
arch/powerpc/boot/ps3.c
arch/powerpc/include/asm/opal.h
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/setup.h
arch/powerpc/include/uapi/asm/unistd.h
arch/powerpc/kernel/kvm.c
arch/powerpc/kernel/machine_kexec_64.c
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kernel/rtas_flash.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_native_64.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/perf/hv-24x7.c
arch/powerpc/perf/hv-gpci.c
arch/powerpc/platforms/powernv/eeh-ioda.c
arch/powerpc/platforms/powernv/opal-dump.c
arch/powerpc/platforms/powernv/opal-elog.c
arch/powerpc/platforms/powernv/opal-flash.c
arch/powerpc/platforms/powernv/opal-sysparam.c
arch/powerpc/platforms/powernv/opal.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/setup.c
arch/powerpc/platforms/powernv/smp.c
arch/powerpc/platforms/pseries/hotplug-cpu.c
arch/powerpc/platforms/pseries/hotplug-memory.c
arch/powerpc/sysdev/ppc4xx_pci.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/boot/header.S
arch/x86/include/asm/hpet.h
arch/x86/include/asm/hugetlb.h
arch/x86/include/asm/page_64_types.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/common.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/perf_event_intel_rapl.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/irq.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/smpboot.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/efi/efi.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/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/ec.c
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/base/dd.c
drivers/base/platform.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/clk/versatile/clk-vexpress-osc.c
drivers/clocksource/arm_arch_timer.c
drivers/clocksource/tcb_clksrc.c
drivers/clocksource/timer-marco.c
drivers/clocksource/zevio-timer.c
drivers/connector/cn_proc.c
drivers/cpufreq/cpufreq-cpu0.c
drivers/cpufreq/cpufreq_governor.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/longhaul.c
drivers/cpufreq/loongson2_cpufreq.c
drivers/cpufreq/powernow-k6.c
drivers/cpufreq/powernow-k7.c
drivers/cpufreq/ppc-corenet-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/gpio-ich.c
drivers/gpio/gpio-mcp23s08.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/exynos/exynos_drm_crtc.c
drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
drivers/gpu/drm/exynos/exynos_drm_dsi.c
drivers/gpu/drm/exynos/exynos_drm_vidi.c
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/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
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_drv.h
drivers/gpu/drm/i915/intel_fbdev.c
drivers/gpu/drm/i915/intel_hdmi.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_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_uncore.c
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
drivers/gpu/drm/msm/msm_fbdev.c
drivers/gpu/drm/msm/msm_gem.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/gpu/drm/tegra/dc.c
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.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/coretemp.c
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/cxgb4/Kconfig
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/cxgb4/iw_cxgb4.h
drivers/infiniband/hw/cxgb4/qp.c
drivers/infiniband/hw/cxgb4/t4fw_ri_api.h
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx4/mlx4_ib.h
drivers/infiniband/hw/mlx4/qp.c
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/irqchip/irq-armada-370-xp.c
drivers/irqchip/irq-crossbar.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/dm-verity.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/led.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/ibm/emac/mal.c
drivers/net/ethernet/ibm/emac/mal.h
drivers/net/ethernet/ibm/emac/rgmii.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_dcb.c
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/ipheth.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/of/irq.c
drivers/of/platform.c
drivers/of/selftest.c
drivers/of/testcase-data/tests-interrupts.dtsi
drivers/pci/host/pci-mvebu.c
drivers/pci/hotplug/shpchp_ctrl.c
drivers/pci/pci.c
drivers/pinctrl/pinctrl-as3722.c
drivers/pinctrl/pinctrl-single.c
drivers/pinctrl/pinctrl-tb10x.c
drivers/pinctrl/sh-pfc/pfc-r8a7790.c
drivers/pinctrl/sh-pfc/pfc-r8a7791.c
drivers/pinctrl/vt8500/pinctrl-wmt.c
drivers/pnp/pnpacpi/core.c
drivers/pnp/pnpbios/bioscalls.c
drivers/pnp/quirks.c
drivers/ptp/Kconfig
drivers/rtc/rtc-hym8563.c
drivers/rtc/rtc-pcf8523.c
drivers/s390/cio/chsc.c
drivers/scsi/mpt2sas/mpt2sas_scsih.c
drivers/scsi/scsi_netlink.c
drivers/scsi/scsi_transport_sas.c
drivers/scsi/virtio_scsi.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/comedi/drivers/ni_daq_700.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/rtl8192e/rtllib_tx.c
drivers/staging/rtl8723au/os_dep/os_intfs.c
drivers/staging/rtl8723au/os_dep/usb_ops_linux.c
drivers/staging/speakup/main.c
drivers/staging/speakup/selection.c
drivers/staging/speakup/speakup.h
drivers/staging/speakup/speakup_acntsa.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/core/driver.c
drivers/usb/core/hub.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/host/pci-quirks.c
drivers/usb/host/xhci-mem.c
drivers/usb/phy/phy-fsm-usb.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/io_ti.c
drivers/usb/serial/io_usbvend.h
drivers/usb/serial/option.c
drivers/usb/serial/qcserial.c
drivers/usb/storage/shuttle_usbat.c
drivers/usb/storage/unusual_devs.h
drivers/xen/events/events_fifo.c
fs/affs/super.c
fs/afs/cmservice.c
fs/afs/internal.h
fs/afs/rxrpc.c
fs/aio.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/kernfs/mount.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/proc/task_mmu.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/fixmap.h
include/asm-generic/resource.h
include/asm-generic/word-at-a-time.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/ftrace.h
include/linux/hugetlb.h
include/linux/if_macvlan.h
include/linux/if_team.h
include/linux/if_vlan.h
include/linux/interrupt.h
include/linux/irq.h
include/linux/kernfs.h
include/linux/linkage.h
include/linux/mfd/rtsx_common.h
include/linux/mfd/rtsx_pci.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_irq.h
include/linux/of_mdio.h
include/linux/omap-dma.h
include/linux/percpu-refcount.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/inetpeer.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/uapi/linux/usb/Kbuild
include/uapi/linux/usb/cdc-wdm.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/irq/irqdesc.c
kernel/kexec.c
kernel/locking/lockdep.c
kernel/locking/rtmutex.c
kernel/module.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/sched/sched.h
kernel/softirq.c
kernel/timer.c
kernel/trace/ftrace.c
kernel/trace/trace_events_trigger.c
kernel/tracepoint.c
kernel/workqueue.c
lib/dump_stack.c
lib/nlattr.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/mempolicy.c
mm/mremap.c
mm/page-writeback.c
mm/percpu.c
mm/rmap.c
mm/slab.c
mm/slab.h
mm/slab_common.c
mm/slub.c
mm/truncate.c
mm/util.c
mm/vmacache.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/multicast.c
net/batman-adv/originator.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_event.c
net/bluetooth/l2cap_core.c
net/bridge/br_fdb.c
net/bridge/br_input.c
net/bridge/br_netfilter.c
net/bridge/br_netlink.c
net/bridge/br_private.h
net/bridge/br_vlan.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_input.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/output_core.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/ipvs/ip_vs_core.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_controller.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_priv.h
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/alc5623.c
sound/soc/codecs/cs42l52.c
sound/soc/codecs/cs42l73.c
sound/soc/codecs/tlv320aic31xx.c
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm8962.h
sound/soc/fsl/fsl_esai.c
sound/soc/fsl/fsl_spdif.h
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/jz4740/Makefile
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/src.c
sound/soc/sh/rcar/ssi.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/api/fs/debugfs.c
tools/lib/lockdep/Makefile
tools/lib/traceevent/event-parse.c
tools/lib/traceevent/event-parse.h
tools/net/bpf_dbg.c
tools/perf/Makefile.perf
tools/perf/arch/x86/tests/dwarf-unwind.c
tools/perf/arch/x86/tests/regs_load.S
tools/perf/config/Makefile
tools/perf/tests/make
tools/perf/util/dwarf-aux.c
tools/perf/util/machine.c
tools/perf/util/probe-finder.c
virt/kvm/arm/vgic.c
virt/kvm/assigned-dev.c
virt/kvm/async_pf.c

index a3c5a66..ab8d76d 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 677a025..ba60d93 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 f9fd615..1d27f0a 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 fa0151a..5c9a567 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 05a27e9..2f51735 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 06fc760..37b2caf 100644 (file)
@@ -19,6 +19,9 @@ to deliver its interrupts via SPIs.
 
 - clock-frequency : The frequency of the main counter, in Hz. Optional.
 
+- always-on : a boolean property. If present, the timer is powered through an
+  always-on power domain, therefore it never loses context.
+
 Example:
 
        timer {
index 7bcfbf5..a668f0e 100644 (file)
@@ -24,6 +24,7 @@ Required properties:
   * "sata-phy" for the SATA 6.0Gbps PHY
 
 Optional properties:
+- dma-coherent         : Present if dma operations are coherent
 - status               : Shall be "ok" if enabled or "disabled" if disabled.
                          Default is "ok".
 
@@ -55,6 +56,7 @@ Example:
                              <0x0 0x1f22e000 0x0 0x1000>,
                              <0x0 0x1f227000 0x0 0x1000>;
                        interrupts = <0x0 0x87 0x4>;
+                       dma-coherent;
                        status = "ok";
                        clocks = <&sataclk 0>;
                        phys = <&phy2 0>;
@@ -69,6 +71,7 @@ Example:
                              <0x0 0x1f23e000 0x0 0x1000>,
                              <0x0 0x1f237000 0x0 0x1000>;
                        interrupts = <0x0 0x88 0x4>;
+                       dma-coherent;
                        status = "ok";
                        clocks = <&sataclk 0>;
                        phys = <&phy3 0>;
index cd5e239..6794cdc 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 5992dce..02a25d9 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 9fbbdb7..68ff213 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 7fbb027..a1d71eb 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 c79bab0..8dbcf82 100644 (file)
@@ -14,7 +14,7 @@ node.
 Example:
 
 aliases {
-       mdio-gpio0 = <&mdio0>;
+       mdio-gpio0 = &mdio0;
 };
 
 mdio0: mdio {
index 636f0ac..2a60cd3 100644 (file)
@@ -23,5 +23,5 @@ gmac0: ethernet@ff700000 {
        interrupt-names = "macirq";
        mac-address = [00 00 00 00 00 00];/* Filled in by U-Boot */
        clocks = <&emac_0_clk>;
-       clocks-names = "stmmaceth";
+       clock-names = "stmmaceth";
 };
index 80c1fb8..a2acd2b 100644 (file)
@@ -33,7 +33,7 @@ Optional properties:
 - max-frame-size: See ethernet.txt file in the same directory
 - clocks: If present, the first clock should be the GMAC main clock,
   further clocks may be specified in derived bindings.
-- clocks-names: One name for each entry in the clocks property, the
+- clock-names: One name for each entry in the clocks property, the
   first one should be "stmmaceth".
 
 Examples:
index 4bd5be0..26bcb18 100644 (file)
@@ -83,7 +83,7 @@ Example:
                reg             = <0xfe61f080 0x4>;
                reg-names       = "irqmux";
                interrupts      = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
-               interrupts-names = "irqmux";
+               interrupt-names = "irqmux";
                ranges          = <0 0xfe610000 0x5000>;
 
                PIO0: gpio@fe610000 {
@@ -165,7 +165,7 @@ sdhci0:sdhci@fe810000{
        interrupt-parent = <&PIO3>;
        #interrupt-cells = <2>;
        interrupts = <3 IRQ_TYPE_LEVEL_HIGH>; /* Interrupt line via PIO3-3 */
-       interrupts-names = "card-detect";
+       interrupt-names = "card-detect";
        pinctrl-names = "default";
        pinctrl-0       = <&pinctrl_mmc>;
 };
index 569b26c..60ca079 100644 (file)
@@ -47,7 +47,7 @@ mcasp0: mcasp0@1d00000 {
        reg = <0x100000 0x3000>;
        reg-names "mpu";
        interrupts = <82>, <83>;
-       interrupts-names = "tx", "rx";
+       interrupt-names = "tx", "rx";
        op-mode = <0>;          /* MCASP_IIS_MODE */
        tdm-slots = <2>;
        serial-dir = <
index 74c66de..eff12be 100644 (file)
@@ -13,6 +13,9 @@ Required properties:
     "ti,tlv320aic3111" - TLV320AIC3111 (stereo speaker amp, MiniDSP)
 
 - reg - <int> -  I2C slave address
+- HPVDD-supply, SPRVDD-supply, SPLVDD-supply, AVDD-supply, IOVDD-supply,
+  DVDD-supply : power supplies for the device as covered in
+  Documentation/devicetree/bindings/regulator/regulator.txt
 
 
 Optional properties:
@@ -24,9 +27,6 @@ Optional properties:
         3 or MICBIAS_AVDD - MICBIAS output is connected to AVDD
        If this node is not mentioned or if the value is unknown, then
        micbias is set to 2.0V.
-- HPVDD-supply, SPRVDD-supply, SPLVDD-supply, AVDD-supply, IOVDD-supply,
-  DVDD-supply : power supplies for the device as covered in
-  Documentation/devicetree/bindings/regulator/regulator.txt
 
 CODEC output pins:
   * HPL
index e9f5dac..4e30eba 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 8b9cd8e..264bcde 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 79f8257..2cc95ad 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 5602eb7..e1ae127 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 e6a7232..4180205 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 4384217..30a8ad0 100644 (file)
@@ -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 81f940f..e3ba753 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 6fea79e..38112d5 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 ca6977f..99ca40e 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 a9380ba..b4f5365 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 e67ea24..6c484ac 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>
@@ -3158,10 +3153,9 @@ S:       Maintained
 F:     drivers/scsi/eata_pio.*
 
 EBTABLES
-M:     Bart De Schuymer <bart.de.schuymer@pandora.be>
 L:     netfilter-devel@vger.kernel.org
 W:     http://ebtables.sourceforge.net/
-S:     Maintained
+S:     Orphan
 F:     include/linux/netfilter_bridge/ebt_*.h
 F:     include/uapi/linux/netfilter_bridge/ebt_*.h
 F:     net/bridge/netfilter/ebt*.c
@@ -3485,6 +3479,12 @@ S:       Maintained
 F:     drivers/extcon/
 F:     Documentation/extcon/
 
+EXYNOS DP DRIVER
+M:     Jingoo Han <jg1.han@samsung.com>
+L:     dri-devel@lists.freedesktop.org
+S:     Maintained
+F:     drivers/gpu/drm/exynos/exynos_dp*
+
 EXYNOS MIPI DISPLAY DRIVERS
 M:     Inki Dae <inki.dae@samsung.com>
 M:     Donghwa Lee <dh09.lee@samsung.com>
@@ -3550,7 +3550,7 @@ F:        include/scsi/libfcoe.h
 F:     include/uapi/scsi/fc/
 
 FILE LOCKING (flock() and fcntl()/lockf())
-M:     Jeff Layton <jlayton@redhat.com>
+M:     Jeff Layton <jlayton@poochiereds.net>
 M:     J. Bruce Fields <bfields@fieldses.org>
 L:     linux-fsdevel@vger.kernel.org
 S:     Maintained
@@ -4812,6 +4812,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)
@@ -5108,14 +5116,19 @@ F:      drivers/s390/kvm/
 
 KERNEL VIRTUAL MACHINE (KVM) FOR ARM
 M:     Christoffer Dall <christoffer.dall@linaro.org>
+M:     Marc Zyngier <marc.zyngier@arm.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     kvmarm@lists.cs.columbia.edu
 W:     http://systems.cs.columbia.edu/projects/kvm-arm
 S:     Supported
 F:     arch/arm/include/uapi/asm/kvm*
 F:     arch/arm/include/asm/kvm*
 F:     arch/arm/kvm/
+F:     virt/kvm/arm/
+F:     include/kvm/arm_*
 
 KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64)
+M:     Christoffer Dall <christoffer.dall@linaro.org>
 M:     Marc Zyngier <marc.zyngier@arm.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     kvmarm@lists.cs.columbia.edu
@@ -5479,15 +5492,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
@@ -6500,10 +6513,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/
 
@@ -7277,7 +7290,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)
@@ -7293,7 +7305,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
 
@@ -7392,6 +7404,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
@@ -7674,7 +7694,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
@@ -9098,6 +9117,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
@@ -9951,7 +9973,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
@@ -9996,7 +10018,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 041c685..cdaa5b6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 15
 SUBLEVEL = 0
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc8
 NAME = Shuffling Zombie Juror
 
 # *DOCUMENTATION*
index 819dd5f..29b82ad 100644 (file)
@@ -614,11 +614,13 @@ resume_user_mode_begin:
 
 resume_kernel_mode:
 
-#ifdef CONFIG_PREEMPT
-
-       ; This is a must for preempt_schedule_irq()
+       ; Disable Interrupts from this point on
+       ; CONFIG_PREEMPT: This is a must for preempt_schedule_irq()
+       ; !CONFIG_PREEMPT: To ensure restore_regs is intr safe
        IRQ_DISABLE     r9
 
+#ifdef CONFIG_PREEMPT
+
        ; Can't preempt if preemption disabled
        GET_CURR_THR_INFO_FROM_SP   r10
        ld  r8, [r10, THREAD_INFO_PREEMPT_COUNT]
index 07f283c..7ad75b4 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>;
                              <0x46000000 0x400000>;
                        reg-names = "mpu", "dat";
                        interrupts = <80>, <81>;
-                       interrupts-names = "tx", "rx";
+                       interrupt-names = "tx", "rx";
                        status = "disabled";
                        dmas = <&edma 8>,
                                <&edma 9>;
                              <0x46400000 0x400000>;
                        reg-names = "mpu", "dat";
                        interrupts = <82>, <83>;
-                       interrupts-names = "tx", "rx";
+                       interrupt-names = "tx", "rx";
                        status = "disabled";
                        dmas = <&edma 10>,
                                <&edma 11>;
index 788391f..5a452fd 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 36d523a..d1f8707 100644 (file)
                              <0x46000000 0x400000>;
                        reg-names = "mpu", "dat";
                        interrupts = <80>, <81>;
-                       interrupts-names = "tx", "rx";
+                       interrupt-names = "tx", "rx";
                        status = "disabled";
                        dmas = <&edma 8>,
                               <&edma 9>;
                              <0x46400000 0x400000>;
                        reg-names = "mpu", "dat";
                        interrupts = <82>, <83>;
-                       interrupts-names = "tx", "rx";
+                       interrupt-names = "tx", "rx";
                        status = "disabled";
                        dmas = <&edma 10>,
                               <&edma 11>;
index df8798e..a055f7f 100644 (file)
        status = "okay";
 };
 
+&gpio5 {
+       status = "okay";
+       ti,no-reset-on-init;
+};
+
 &mmc1 {
        status = "okay";
        vmmc-supply = <&vmmcsd_fixed>;
index 82f238a..3383c4b 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 9378d31..0451124 100644 (file)
                                };
                        };
 
+                       sata@a0000 {
+                               status = "okay";
+                               nr-ports = <2>;
+                       };
+
                        nand: nand@d0000 {
                                pinctrl-0 = <&nand_pins>;
                                pinctrl-names = "default";
index 068031f..6d0f03c 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 e2919f0..da80196 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 448373c..90f0bf6 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 61bda68..0c75642 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 985948c..5d42feb 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 ce13755..4537259 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 366fc2c..c0e0eae 100644 (file)
                                trigger@3 {
                                        reg = <3>;
                                        trigger-name = "external";
-                                       trigger-value = <0x13>;
+                                       trigger-value = <0xd>;
                                        trigger-external;
                                };
                        };
index e21dda0..3be973e 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 63e1784..92a52fa 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 9583563..8a558b7 100644 (file)
                status = "okay";
 
                ak8975@0c {
-                       compatible = "ak,ak8975";
+                       compatible = "asahi-kasei,ak8975";
                        reg = <0x0c>;
                        gpios = <&gpj0 7 0>;
                };
index 090f983..cde19c8 100644 (file)
                                        regulator-name = "VDD_IOPERI_1.8V";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
                                        op_mode = <1>;
                                };
 
index 80a3bf4..896a2a6 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 c3a9a66..b69fbcb 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 7c8c129..a3431d7 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 9c2bff2..6a1bf4f 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 32c6fb4..b939f4f 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 aa78c2d..e2cc85c 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 7d1c767..0bd70d9 100644 (file)
 
                i2c@11000 {
                        status = "okay";
-
-                       alc5621: alc5621@1a {
-                               compatible = "realtek,alc5621";
-                               reg = <0x1a>;
-                       };
                };
 
                serial@12000 {
index f577b7d..521c587 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 22f35ea..8f8c07d 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 85b1fb0..2d99798 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 d09697d..42d2c61 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 d000558..25ba083 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 b97736d..e2d163b 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 7abd64f..b22caaa 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 7909c51..d59e3de 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 024c9c6..42189b6 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 acb9019..4231191 100644 (file)
@@ -61,7 +61,7 @@
                        ti,hwmods = "mpu";
                };
 
-               iva {
+               iva: iva {
                        compatible = "ti,iva2.2";
                        ti,hwmods = "iva";
 
index f8c9855..36b4312 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 eabcfdb..a106b08 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 b029fe7..1b02208 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 382b044..0284845 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 a9fa75e..7a8d4c6 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 7f3baf5..32dd55e 100644 (file)
@@ -18,6 +18,7 @@
        compatible = "st-ericsson,ccu8540", "st-ericsson,u8540";
 
        memory@0 {
+               device_type = "memory";
                reg = <0x20000000 0x1f000000>, <0xc0000000 0x3f000000>;
        };
 
index f09fb10..81df870 100644 (file)
@@ -49,7 +49,7 @@
                        reg             = <0xfe61f080 0x4>;
                        reg-names       = "irqmux";
                        interrupts      = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupts-names = "irqmux";
+                       interrupt-names = "irqmux";
                        ranges          = <0 0xfe610000 0x5000>;
 
                        PIO0: gpio@fe610000 {
                        reg             = <0xfee0f080 0x4>;
                        reg-names       = "irqmux";
                        interrupts      = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupts-names = "irqmux";
+                       interrupt-names = "irqmux";
                        ranges          = <0 0xfee00000 0x8000>;
 
                        PIO5: gpio@fee00000 {
                        reg             = <0xfe82f080 0x4>;
                        reg-names       = "irqmux";
                        interrupts      = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupts-names = "irqmux";
+                       interrupt-names = "irqmux";
                        ranges          = <0 0xfe820000 0x8000>;
 
                        PIO13: gpio@fe820000 {
                        reg             = <0xfd6bf080 0x4>;
                        reg-names       = "irqmux";
                        interrupts      = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupts-names = "irqmux";
+                       interrupt-names = "irqmux";
                        ranges          = <0 0xfd6b0000 0x3000>;
 
                        PIO100: gpio@fd6b0000 {
                        reg             = <0xfd33f080 0x4>;
                        reg-names       = "irqmux";
                        interrupts      = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupts-names = "irqmux";
+                       interrupt-names = "irqmux";
                        ranges          = <0 0xfd330000 0x5000>;
 
                        PIO103: gpio@fd330000 {
index aeea304..250d5ec 100644 (file)
@@ -53,7 +53,7 @@
                        reg             = <0xfe61f080 0x4>;
                        reg-names       = "irqmux";
                        interrupts      = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupts-names = "irqmux";
+                       interrupt-names = "irqmux";
                        ranges          = <0 0xfe610000 0x6000>;
 
                        PIO0: gpio@fe610000 {
                        reg             = <0xfee0f080 0x4>;
                        reg-names       = "irqmux";
                        interrupts      = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupts-names = "irqmux";
+                       interrupt-names = "irqmux";
                        ranges          = <0 0xfee00000 0x10000>;
 
                        PIO5: gpio@fee00000 {
                        reg             = <0xfe82f080 0x4>;
                        reg-names       = "irqmux";
                        interrupts      = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupts-names = "irqmux";
+                       interrupt-names = "irqmux";
                        ranges          = <0 0xfe820000 0x6000>;
 
                        PIO13: gpio@fe820000 {
                        reg             = <0xfd6bf080 0x4>;
                        reg-names       = "irqmux";
                        interrupts      = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupts-names = "irqmux";
+                       interrupt-names = "irqmux";
                        ranges          = <0 0xfd6b0000 0x3000>;
 
                        PIO100: gpio@fd6b0000 {
                        reg             = <0xfd33f080 0x4>;
                        reg-names       = "irqmux";
                        interrupts      = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupts-names = "irqmux";
+                       interrupt-names = "irqmux";
                        ranges                  = <0 0xfd330000 0x5000>;
 
                        PIO103: gpio@fd330000 {
index 32efc10..aba1c8a 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 f01c0ee..490f3dc 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 41bca32..5339009 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 4ce7b70..e07a227 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 b5df4a5..81ba78e 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 b5f7705..624e1d4 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 12c3a5d..75d9579 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 cf4f3e8..ded062f 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 1420725..efb208d 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 3c21769..cb791ac 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 466bd29..4be5bb1 100644 (file)
@@ -23,7 +23,7 @@ config KVM
        select HAVE_KVM_CPU_RELAX_INTERCEPT
        select KVM_MMIO
        select KVM_ARM_HOST
-       depends on ARM_VIRT_EXT && ARM_LPAE
+       depends on ARM_VIRT_EXT && ARM_LPAE && !CPU_BIG_ENDIAN
        ---help---
          Support hosting virtualized guest machines. You will also
          need to select one or more of the processor modules below.
index 80bb1e6..16f8049 100644 (file)
@@ -42,6 +42,8 @@ static unsigned long hyp_idmap_start;
 static unsigned long hyp_idmap_end;
 static phys_addr_t hyp_idmap_vector;
 
+#define pgd_order get_order(PTRS_PER_PGD * sizeof(pgd_t))
+
 #define kvm_pmd_huge(_x)       (pmd_huge(_x) || pmd_trans_huge(_x))
 
 static void kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
@@ -293,14 +295,14 @@ void free_boot_hyp_pgd(void)
        if (boot_hyp_pgd) {
                unmap_range(NULL, boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE);
                unmap_range(NULL, boot_hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
-               kfree(boot_hyp_pgd);
+               free_pages((unsigned long)boot_hyp_pgd, pgd_order);
                boot_hyp_pgd = NULL;
        }
 
        if (hyp_pgd)
                unmap_range(NULL, hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
 
-       kfree(init_bounce_page);
+       free_page((unsigned long)init_bounce_page);
        init_bounce_page = NULL;
 
        mutex_unlock(&kvm_hyp_pgd_mutex);
@@ -330,7 +332,7 @@ void free_hyp_pgds(void)
                for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE)
                        unmap_range(NULL, hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
 
-               kfree(hyp_pgd);
+               free_pages((unsigned long)hyp_pgd, pgd_order);
                hyp_pgd = NULL;
        }
 
@@ -1024,7 +1026,7 @@ int kvm_mmu_init(void)
                size_t len = __hyp_idmap_text_end - __hyp_idmap_text_start;
                phys_addr_t phys_base;
 
-               init_bounce_page = kmalloc(PAGE_SIZE, GFP_KERNEL);
+               init_bounce_page = (void *)__get_free_page(GFP_KERNEL);
                if (!init_bounce_page) {
                        kvm_err("Couldn't allocate HYP init bounce page\n");
                        err = -ENOMEM;
@@ -1050,8 +1052,9 @@ int kvm_mmu_init(void)
                         (unsigned long)phys_base);
        }
 
-       hyp_pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL);
-       boot_hyp_pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL);
+       hyp_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, pgd_order);
+       boot_hyp_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, pgd_order);
+
        if (!hyp_pgd || !boot_hyp_pgd) {
                kvm_err("Hyp mode PGD not allocated\n");
                err = -ENOMEM;
index a028292..7cd6f19 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 932129e..aa01c42 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 fc4dd7c..6bd7c3f 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 f3d4cf5..09520e1 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 ac82512..b6885e4 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 8f5121b..eb8c75e 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 01fc710..2498ab0 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 75e9295..40c5d5f 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 8923172..e829664 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 f565f99..7548db2 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 0c93588..1ca37c7 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 5f5b975..b5608b1 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 93f4b2d..f8c40a6 100644 (file)
                              <0x0 0x1f21e000 0x0 0x1000>,
                              <0x0 0x1f217000 0x0 0x1000>;
                        interrupts = <0x0 0x86 0x4>;
+                       dma-coherent;
                        status = "disabled";
                        clocks = <&sata01clk 0>;
                        phys = <&phy1 0>;
                              <0x0 0x1f22e000 0x0 0x1000>,
                              <0x0 0x1f227000 0x0 0x1000>;
                        interrupts = <0x0 0x87 0x4>;
+                       dma-coherent;
                        status = "ok";
                        clocks = <&sata23clk 0>;
                        phys = <&phy2 0>;
                              <0x0 0x1f23d000 0x0 0x1000>,
                              <0x0 0x1f23e000 0x0 0x1000>;
                        interrupts = <0x0 0x88 0x4>;
+                       dma-coherent;
                        status = "ok";
                        clocks = <&sata45clk 0>;
                        phys = <&phy3 0>;
index e94f945..993bce5 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 90c811f..7b1c67a 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 ffbbdde..2dc36d0 100644 (file)
@@ -143,10 +143,8 @@ static int __init setup_early_printk(char *buf)
        }
        /* no options parsing yet */
 
-       if (paddr) {
-               set_fixmap_io(FIX_EARLYCON_MEM_BASE, paddr);
-               early_base = (void __iomem *)fix_to_virt(FIX_EARLYCON_MEM_BASE);
-       }
+       if (paddr)
+               early_base = (void __iomem *)set_fixmap_offset_io(FIX_EARLYCON_MEM_BASE, paddr);
 
        printch = match->printch;
        early_console = &early_console_dev;
index 473e5db..0f08dfd 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 93e7df8..7ec7846 100644 (file)
@@ -396,7 +396,7 @@ static int __init arm64_device_init(void)
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
        return 0;
 }
-arch_initcall(arm64_device_init);
+arch_initcall_sync(arm64_device_init);
 
 static DEFINE_PER_CPU(struct cpu, cpu_data);
 
index 0ba347e..c851eb4 100644 (file)
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-contiguous.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 #include <linux/vmalloc.h>
 #include <linux/swiotlb.h>
+#include <linux/amba/bus.h>
 
 #include <asm/cacheflush.h>
 
@@ -305,17 +308,45 @@ struct dma_map_ops coherent_swiotlb_dma_ops = {
 };
 EXPORT_SYMBOL(coherent_swiotlb_dma_ops);
 
+static int dma_bus_notifier(struct notifier_block *nb,
+                           unsigned long event, void *_dev)
+{
+       struct device *dev = _dev;
+
+       if (event != BUS_NOTIFY_ADD_DEVICE)
+               return NOTIFY_DONE;
+
+       if (of_property_read_bool(dev->of_node, "dma-coherent"))
+               set_dma_ops(dev, &coherent_swiotlb_dma_ops);
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block platform_bus_nb = {
+       .notifier_call = dma_bus_notifier,
+};
+
+static struct notifier_block amba_bus_nb = {
+       .notifier_call = dma_bus_notifier,
+};
+
 extern int swiotlb_late_init_with_default_size(size_t default_size);
 
 static int __init swiotlb_late_init(void)
 {
        size_t swiotlb_size = min(SZ_64M, MAX_ORDER_NR_PAGES << PAGE_SHIFT);
 
-       dma_ops = &coherent_swiotlb_dma_ops;
+       /*
+        * These must be registered before of_platform_populate().
+        */
+       bus_register_notifier(&platform_bus_type, &platform_bus_nb);
+       bus_register_notifier(&amba_bustype, &amba_bus_nb);
+
+       dma_ops = &noncoherent_swiotlb_dma_ops;
 
        return swiotlb_late_init_with_default_size(swiotlb_size);
 }
-subsys_initcall(swiotlb_late_init);
+arch_initcall(swiotlb_late_init);
 
 #define PREALLOC_DMA_DEBUG_ENTRIES     4096
 
index 5e9aec3..31eb959 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 6b7e895..0a472c4 100644 (file)
@@ -374,6 +374,9 @@ int kern_addr_valid(unsigned long addr)
        if (pmd_none(*pmd))
                return 0;
 
+       if (pmd_sect(*pmd))
+               return pfn_valid(pmd_pfn(*pmd));
+
        pte = pte_offset_kernel(pmd, addr);
        if (pte_none(*pte))
                return 0;
diff --git a/arch/hexagon/include/asm/barrier.h b/arch/hexagon/include/asm/barrier.h
deleted file mode 100644 (file)
index 4e863da..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Memory barrier definitions for the Hexagon architecture
- *
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef _ASM_BARRIER_H
-#define _ASM_BARRIER_H
-
-#define rmb()                          barrier()
-#define read_barrier_depends()         barrier()
-#define wmb()                          barrier()
-#define mb()                           barrier()
-#define smp_rmb()                      barrier()
-#define smp_read_barrier_depends()     barrier()
-#define smp_wmb()                      barrier()
-#define smp_mb()                       barrier()
-
-/*  Set a value and use a memory barrier.  Used by the scheduler somewhere.  */
-#define set_mb(var, value) \
-       do { var = value; mb(); } while (0)
-
-#endif /* _ASM_BARRIER_H */
index ae763d8..fb13dc5 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 715e85f..7de0a2d 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 fa8d61a..ba3d035 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 9d38b73..33afa56 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 b932dd4..9cd82fb 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 b6223dc..501e102 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 5d6b4b4..2d6f0de 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 f16477d..a8a3747 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 84e09fe..ab78be2 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 1a5b403..60a359c 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 5abf4e8..2a66e90 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 f434b75..ec60636 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 064ae7a..ae73e42 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 b308b2a..4703fe4 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 2c2cb18..6aa264b 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 dc2135b..ff2707a 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 c0ead63..b59a210 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 c6e9cd2..17960fe 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 df6e775..3125797 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 d6e154a..5805414 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 4d78bf4..76122ff 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 e40971b..037a44d 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 71f85f4..f639ccd 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 fdc70b4..3245474 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 dd99c32..be2fedd 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 f68d2f4..c1dbcda 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 70f6ace..f1343cc 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 074e857..8119ac2 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 fac1f5b..143b8a3 100644 (file)
@@ -8,6 +8,7 @@
        };
 
        memory@0 {
+               device_type = "memory";
                reg = <0x0 0x2000000>;
        };
 
index 2e4825e..9901237 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 44713af..705cfb7 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 d3301cd..3c32baf 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 7397be2..603d79a 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 c639b9d..12c75db 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 e1f427f..67dd94e 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 58033c4..b611102 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 30a494d..a5427c6 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 ee88367..f99ec58 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 6d0f4ab..f2364e4 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 b128cb9..7f6ce6d 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 35eb874..709f581 100644 (file)
@@ -7,6 +7,7 @@
        model = "Ralink MT7620A evaluation board";
 
        memory@0 {
+               device_type = "memory";
                reg = <0x0 0x2000000>;
        };
 
index 322d700..0a685db 100644 (file)
@@ -7,6 +7,7 @@
        model = "Ralink RT2880 evaluation board";
 
        memory@0 {
+               device_type = "memory";
                reg = <0x8000000 0x2000000>;
        };
 
index 0ac73ea..ec9e9a0 100644 (file)
@@ -7,6 +7,7 @@
        model = "Ralink RT3052 evaluation board";
 
        memory@0 {
+               device_type = "memory";
                reg = <0x0 0x2000000>;
        };
 
index 2fa6b33..e8df21a 100644 (file)
@@ -7,6 +7,7 @@
        model = "Ralink RT3883 evaluation board";
 
        memory@0 {
+               device_type = "memory";
                reg = <0x0 0x2000000>;
        };
 
index 1faefed..108d48e 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 198a86f..d951c96 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 a580642..348356c 100644 (file)
@@ -1,6 +1,8 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+generic-y += resource.h
+
 header-y += bitsperlong.h
 header-y += byteorder.h
 header-y += errno.h
@@ -13,7 +15,6 @@ header-y += msgbuf.h
 header-y += pdc.h
 header-y += posix_types.h
 header-y += ptrace.h
-header-y += resource.h
 header-y += sembuf.h
 header-y += setup.h
 header-y += shmbuf.h
diff --git a/arch/parisc/include/uapi/asm/resource.h b/arch/parisc/include/uapi/asm/resource.h
deleted file mode 100644 (file)
index 8b06343..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _ASM_PARISC_RESOURCE_H
-#define _ASM_PARISC_RESOURCE_H
-
-#define _STK_LIM_MAX   10 * _STK_LIM
-#include <asm-generic/resource.h>
-
-#endif
index 265ae51..47e0e21 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 31ffa9b..e1ffea2 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 a63bb17..8387860 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 83ead0e..c5fa7a6 100644 (file)
        ENTRY_SAME(sched_setattr)
        ENTRY_SAME(sched_getattr)       /* 335 */
        ENTRY_COMP(utimes)
+       ENTRY_SAME(renameat2)
 
        /* Nothing yet */
 
index 1cd1d0c..47ee620 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 7475507..3ca9c11 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 4c0cedf..ce4c68a 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 a28f021..d367a0a 100644 (file)
@@ -139,18 +139,18 @@ static struct addr_range prep_initrd(struct addr_range vmlinux, void *chosen,
  * edit the command line passed to vmlinux (by setting /chosen/bootargs).
  * The buffer is put in it's own section so that tools may locate it easier.
  */
-static char cmdline[COMMAND_LINE_SIZE]
+static char cmdline[BOOT_COMMAND_LINE_SIZE]
        __attribute__((__section__("__builtin_cmdline")));
 
 static void prep_cmdline(void *chosen)
 {
        if (cmdline[0] == '\0')
-               getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1);
+               getprop(chosen, "bootargs", cmdline, BOOT_COMMAND_LINE_SIZE-1);
 
        printf("\n\rLinux/PowerPC load: %s", cmdline);
        /* If possible, edit the command line */
        if (console_ops.edit_cmdline)
-               console_ops.edit_cmdline(cmdline, COMMAND_LINE_SIZE);
+               console_ops.edit_cmdline(cmdline, BOOT_COMMAND_LINE_SIZE);
        printf("\n\r");
 
        /* Put the command line back into the devtree for the kernel */
@@ -174,7 +174,7 @@ void start(void)
         * built-in command line wasn't set by an external tool */
        if ((loader_info.cmdline_len > 0) && (cmdline[0] == '\0'))
                memmove(cmdline, loader_info.cmdline,
-                       min(loader_info.cmdline_len, COMMAND_LINE_SIZE-1));
+                       min(loader_info.cmdline_len, BOOT_COMMAND_LINE_SIZE-1));
 
        if (console_ops.open && (console_ops.open() < 0))
                exit();
index b3218ce..8aad3c5 100644 (file)
@@ -15,7 +15,7 @@
 #include "types.h"
 #include "string.h"
 
-#define        COMMAND_LINE_SIZE       512
+#define        BOOT_COMMAND_LINE_SIZE  2048
 #define        MAX_PATH_LEN            256
 #define        MAX_PROP_LEN            256 /* What should this be? */
 
index 9954d98..4ec2d86 100644 (file)
@@ -47,13 +47,13 @@ BSS_STACK(4096);
  * The buffer is put in it's own section so that tools may locate it easier.
  */
 
-static char cmdline[COMMAND_LINE_SIZE]
+static char cmdline[BOOT_COMMAND_LINE_SIZE]
        __attribute__((__section__("__builtin_cmdline")));
 
 static void prep_cmdline(void *chosen)
 {
        if (cmdline[0] == '\0')
-               getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1);
+               getprop(chosen, "bootargs", cmdline, BOOT_COMMAND_LINE_SIZE-1);
        else
                setprop_str(chosen, "bootargs", cmdline);
 
index a2efdaa..66ad7a7 100644 (file)
@@ -41,14 +41,14 @@ struct opal_takeover_args {
  * size except the last one in the list to be as well.
  */
 struct opal_sg_entry {
-       void    *data;
-       long    length;
+       __be64 data;
+       __be64 length;
 };
 
-/* sg list */
+/* SG list */
 struct opal_sg_list {
-       unsigned long num_entries;
-       struct opal_sg_list *next;
+       __be64 length;
+       __be64 next;
        struct opal_sg_entry entry[];
 };
 
@@ -858,8 +858,8 @@ int64_t opal_lpc_write(uint32_t chip_id, enum OpalLPCAddressType addr_type,
 int64_t opal_lpc_read(uint32_t chip_id, enum OpalLPCAddressType addr_type,
                      uint32_t addr, __be32 *data, uint32_t sz);
 
-int64_t opal_read_elog(uint64_t buffer, size_t size, uint64_t log_id);
-int64_t opal_get_elog_size(uint64_t *log_id, size_t *size, uint64_t *elog_type);
+int64_t opal_read_elog(uint64_t buffer, uint64_t size, uint64_t log_id);
+int64_t opal_get_elog_size(__be64 *log_id, __be64 *size, __be64 *elog_type);
 int64_t opal_write_elog(uint64_t buffer, uint64_t size, uint64_t offset);
 int64_t opal_send_ack_elog(uint64_t log_id);
 void opal_resend_pending_logs(void);
@@ -868,23 +868,24 @@ int64_t opal_validate_flash(uint64_t buffer, uint32_t *size, uint32_t *result);
 int64_t opal_manage_flash(uint8_t op);
 int64_t opal_update_flash(uint64_t blk_list);
 int64_t opal_dump_init(uint8_t dump_type);
-int64_t opal_dump_info(uint32_t *dump_id, uint32_t *dump_size);
-int64_t opal_dump_info2(uint32_t *dump_id, uint32_t *dump_size, uint32_t *dump_type);
+int64_t opal_dump_info(__be32 *dump_id, __be32 *dump_size);
+int64_t opal_dump_info2(__be32 *dump_id, __be32 *dump_size, __be32 *dump_type);
 int64_t opal_dump_read(uint32_t dump_id, uint64_t buffer);
 int64_t opal_dump_ack(uint32_t dump_id);
 int64_t opal_dump_resend_notification(void);
 
-int64_t opal_get_msg(uint64_t buffer, size_t size);
-int64_t opal_check_completion(uint64_t buffer, size_t size, uint64_t token);
+int64_t opal_get_msg(uint64_t buffer, uint64_t size);
+int64_t opal_check_completion(uint64_t buffer, uint64_t size, uint64_t token);
 int64_t opal_sync_host_reboot(void);
 int64_t opal_get_param(uint64_t token, uint32_t param_id, uint64_t buffer,
-               size_t length);
+               uint64_t length);
 int64_t opal_set_param(uint64_t token, uint32_t param_id, uint64_t buffer,
-               size_t length);
+               uint64_t length);
 int64_t opal_sensor_read(uint32_t sensor_hndl, int token, __be32 *sensor_data);
 
 /* Internal functions */
-extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
+extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
+                                  int depth, void *data);
 extern int early_init_dt_scan_recoverable_ranges(unsigned long node,
                                 const char *uname, int depth, void *data);
 
@@ -893,10 +894,6 @@ extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
 
 extern void hvc_opal_init_early(void);
 
-/* Internal functions */
-extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
-                                  int depth, void *data);
-
 extern int opal_notifier_register(struct notifier_block *nb);
 extern int opal_notifier_unregister(struct notifier_block *nb);
 
@@ -906,9 +903,6 @@ extern void opal_notifier_enable(void);
 extern void opal_notifier_disable(void);
 extern void opal_notifier_update_evt(uint64_t evt_mask, uint64_t evt_val);
 
-extern int opal_get_chars(uint32_t vtermno, char *buf, int count);
-extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
-
 extern int __opal_async_get_token(void);
 extern int opal_async_get_token_interruptible(void);
 extern int __opal_async_release_token(int token);
@@ -916,8 +910,6 @@ extern int opal_async_release_token(int token);
 extern int opal_async_wait_response(uint64_t token, struct opal_msg *msg);
 extern int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data);
 
-extern void hvc_opal_init_early(void);
-
 struct rtc_time;
 extern int opal_set_rtc_time(struct rtc_time *tm);
 extern void opal_get_rtc_time(struct rtc_time *tm);
@@ -937,6 +929,10 @@ extern int opal_resync_timebase(void);
 
 extern void opal_lpc_init(void);
 
+struct opal_sg_list *opal_vmalloc_to_sg_list(void *vmalloc_addr,
+                                            unsigned long vmalloc_size);
+void opal_free_sg_list(struct opal_sg_list *sg);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __OPAL_H */
index 6586a40..cded7c1 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 d0e784e..5217903 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 3ddf702..ea4dc3a 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 4494f02..9b892bb 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 552df83..ae3fb68 100644 (file)
@@ -1 +1,6 @@
-#include <asm-generic/setup.h>
+#ifndef _UAPI_ASM_POWERPC_SETUP_H
+#define _UAPI_ASM_POWERPC_SETUP_H
+
+#define COMMAND_LINE_SIZE      2048
+
+#endif /* _UAPI_ASM_POWERPC_SETUP_H */
index 881bf2e..2d526f7 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 6a01752..dd8695f 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 59d229a..879b3aa 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 3bd77ed..450850a 100644 (file)
@@ -120,6 +120,7 @@ EXPORT_SYMBOL(giveup_spe);
 EXPORT_SYMBOL(flush_instruction_cache);
 #endif
 EXPORT_SYMBOL(flush_dcache_range);
+EXPORT_SYMBOL(flush_icache_range);
 
 #ifdef CONFIG_SMP
 #ifdef CONFIG_PPC32
index 2f3cdb0..658e89d 100644 (file)
@@ -705,7 +705,7 @@ static int __init rtas_flash_init(void)
        if (rtas_token("ibm,update-flash-64-and-reboot") ==
                       RTAS_UNKNOWN_SERVICE) {
                pr_info("rtas_flash: no firmware flash support\n");
-               return 1;
+               return -EINVAL;
        }
 
        rtas_validate_flash_data.buf = kzalloc(VALIDATE_BUF_SIZE, GFP_KERNEL);
index 122a580..7e711bd 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 94e597e..7af190a 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 1d6c56a..8fcc363 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 ffbb871..07c8b5b 100644 (file)
@@ -242,6 +242,12 @@ kvm_novcpu_exit:
  */
        .globl  kvm_start_guest
 kvm_start_guest:
+
+       /* Set runlatch bit the minute you wake up from nap */
+       mfspr   r1, SPRN_CTRLF
+       ori     r1, r1, 1
+       mtspr   SPRN_CTRLT, r1
+
        ld      r2,PACATOC(r13)
 
        li      r0,KVM_HWTHREAD_IN_KVM
@@ -309,6 +315,11 @@ kvm_no_guest:
        li      r0, KVM_HWTHREAD_IN_NAP
        stb     r0, HSTATE_HWTHREAD_STATE(r13)
 kvm_do_nap:
+       /* Clear the runlatch bit before napping */
+       mfspr   r2, SPRN_CTRLF
+       clrrdi  r2, r2, 1
+       mtspr   SPRN_CTRLT, r2
+
        li      r3, LPCR_PECE0
        mfspr   r4, SPRN_LPCR
        rlwimi  r4, r3, 0, LPCR_PECE0 | LPCR_PECE1
@@ -1312,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
@@ -1999,8 +2114,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
 
        /*
         * Take a nap until a decrementer or external or doobell interrupt
-        * occurs, with PECE1, PECE0 and PECEDP set in LPCR
+        * occurs, with PECE1, PECE0 and PECEDP set in LPCR. Also clear the
+        * runlatch bit before napping.
         */
+       mfspr   r2, SPRN_CTRLF
+       clrrdi  r2, r2, 1
+       mtspr   SPRN_CTRLT, r2
+
        li      r0,1
        stb     r0,HSTATE_HWTHREAD_REQ(r13)
        mfspr   r5,SPRN_LPCR
index c5c052a..02f1def 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 3ea26c2..cf1d325 100644 (file)
@@ -82,17 +82,14 @@ static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize)
                va &= ~((1ul << mmu_psize_defs[apsize].shift) - 1);
                va |= penc << 12;
                va |= ssize << 8;
-               /* Add AVAL part */
-               if (psize != apsize) {
-                       /*
-                        * MPSS, 64K base page size and 16MB parge page size
-                        * We don't need all the bits, but rest of the bits
-                        * must be ignored by the processor.
-                        * vpn cover upto 65 bits of va. (0...65) and we need
-                        * 58..64 bits of va.
-                        */
-                       va |= (vpn & 0xfe);
-               }
+               /*
+                * AVAL bits:
+                * We don't need all the bits, but rest of the bits
+                * must be ignored by the processor.
+                * vpn cover upto 65 bits of va. (0...65) and we need
+                * 58..64 bits of va.
+                */
+               va |= (vpn & 0xfe); /* AVAL */
                va |= 1; /* L */
                asm volatile(ASM_FTR_IFCLR("tlbie %0,1", PPC_TLBIE(%1,%0), %2)
                             : : "r" (va), "r"(0), "i" (CPU_FTR_ARCH_206)
@@ -133,17 +130,14 @@ static inline void __tlbiel(unsigned long vpn, int psize, int apsize, int ssize)
                va &= ~((1ul << mmu_psize_defs[apsize].shift) - 1);
                va |= penc << 12;
                va |= ssize << 8;
-               /* Add AVAL part */
-               if (psize != apsize) {
-                       /*
-                        * MPSS, 64K base page size and 16MB parge page size
-                        * We don't need all the bits, but rest of the bits
-                        * must be ignored by the processor.
-                        * vpn cover upto 65 bits of va. (0...65) and we need
-                        * 58..64 bits of va.
-                        */
-                       va |= (vpn & 0xfe);
-               }
+               /*
+                * AVAL bits:
+                * We don't need all the bits, but rest of the bits
+                * must be ignored by the processor.
+                * vpn cover upto 65 bits of va. (0...65) and we need
+                * 58..64 bits of va.
+                */
+               va |= (vpn & 0xfe);
                va |= 1; /* L */
                asm volatile(".long 0x7c000224 | (%0 << 11) | (1 << 21)"
                             : : "r"(va) : "memory");
index d766d6e..06ba83b 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 297c910..e0766b8 100644 (file)
@@ -155,16 +155,28 @@ static ssize_t read_offset_data(void *dest, size_t dest_len,
        return copy_len;
 }
 
-static unsigned long h_get_24x7_catalog_page(char page[static 4096],
-                                            u32 version, u32 index)
+static unsigned long h_get_24x7_catalog_page_(unsigned long phys_4096,
+                                             unsigned long version,
+                                             unsigned long index)
 {
-       WARN_ON(!IS_ALIGNED((unsigned long)page, 4096));
+       pr_devel("h_get_24x7_catalog_page(0x%lx, %lu, %lu)",
+                       phys_4096,
+                       version,
+                       index);
+       WARN_ON(!IS_ALIGNED(phys_4096, 4096));
        return plpar_hcall_norets(H_GET_24X7_CATALOG_PAGE,
-                       virt_to_phys(page),
+                       phys_4096,
                        version,
                        index);
 }
 
+static unsigned long h_get_24x7_catalog_page(char page[],
+                                            u64 version, u32 index)
+{
+       return h_get_24x7_catalog_page_(virt_to_phys(page),
+                                       version, index);
+}
+
 static ssize_t catalog_read(struct file *filp, struct kobject *kobj,
                            struct bin_attribute *bin_attr, char *buf,
                            loff_t offset, size_t count)
@@ -173,7 +185,7 @@ static ssize_t catalog_read(struct file *filp, struct kobject *kobj,
        ssize_t ret = 0;
        size_t catalog_len = 0, catalog_page_len = 0, page_count = 0;
        loff_t page_offset = 0;
-       uint32_t catalog_version_num = 0;
+       uint64_t catalog_version_num = 0;
        void *page = kmem_cache_alloc(hv_page_cache, GFP_USER);
        struct hv_24x7_catalog_page_0 *page_0 = page;
        if (!page)
@@ -185,7 +197,7 @@ static ssize_t catalog_read(struct file *filp, struct kobject *kobj,
                goto e_free;
        }
 
-       catalog_version_num = be32_to_cpu(page_0->version);
+       catalog_version_num = be64_to_cpu(page_0->version);
        catalog_page_len = be32_to_cpu(page_0->length);
        catalog_len = catalog_page_len * 4096;
 
@@ -208,8 +220,9 @@ static ssize_t catalog_read(struct file *filp, struct kobject *kobj,
                                page, 4096, page_offset * 4096);
 e_free:
        if (hret)
-               pr_err("h_get_24x7_catalog_page(ver=%d, page=%lld) failed: rc=%ld\n",
-                               catalog_version_num, page_offset, hret);
+               pr_err("h_get_24x7_catalog_page(ver=%lld, page=%lld) failed:"
+                      " rc=%ld\n",
+                      catalog_version_num, page_offset, hret);
        kfree(page);
 
        pr_devel("catalog_read: offset=%lld(%lld) count=%zu(%zu) catalog_len=%zu(%zu) => %zd\n",
@@ -243,7 +256,7 @@ e_free:                                                             \
 static DEVICE_ATTR_RO(_name)
 
 PAGE_0_ATTR(catalog_version, "%lld\n",
-               (unsigned long long)be32_to_cpu(page_0->version));
+               (unsigned long long)be64_to_cpu(page_0->version));
 PAGE_0_ATTR(catalog_len, "%lld\n",
                (unsigned long long)be32_to_cpu(page_0->length) * 4096);
 static BIN_ATTR_RO(catalog, 0/* real length varies */);
@@ -485,13 +498,13 @@ static int hv_24x7_init(void)
        struct hv_perf_caps caps;
 
        if (!firmware_has_feature(FW_FEATURE_LPAR)) {
-               pr_info("not a virtualized system, not enabling\n");
+               pr_debug("not a virtualized system, not enabling\n");
                return -ENODEV;
        }
 
        hret = hv_perf_caps_get(&caps);
        if (hret) {
-               pr_info("could not obtain capabilities, error 0x%80lx, not enabling\n",
+               pr_debug("could not obtain capabilities, not enabling, rc=%ld\n",
                                hret);
                return -ENODEV;
        }
index 278ba7b..c9d399a 100644 (file)
@@ -78,7 +78,7 @@ static ssize_t kernel_version_show(struct device *dev,
        return sprintf(page, "0x%x\n", COUNTER_INFO_VERSION_CURRENT);
 }
 
-DEVICE_ATTR_RO(kernel_version);
+static DEVICE_ATTR_RO(kernel_version);
 HV_CAPS_ATTR(version, "0x%x\n");
 HV_CAPS_ATTR(ga, "%d\n");
 HV_CAPS_ATTR(expanded, "%d\n");
@@ -273,13 +273,13 @@ static int hv_gpci_init(void)
        struct hv_perf_caps caps;
 
        if (!firmware_has_feature(FW_FEATURE_LPAR)) {
-               pr_info("not a virtualized system, not enabling\n");
+               pr_debug("not a virtualized system, not enabling\n");
                return -ENODEV;
        }
 
        hret = hv_perf_caps_get(&caps);
        if (hret) {
-               pr_info("could not obtain capabilities, error 0x%80lx, not enabling\n",
+               pr_debug("could not obtain capabilities, not enabling, rc=%ld\n",
                                hret);
                return -ENODEV;
        }
index 253fefe..5b51079 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 b9827b0..788a197 100644 (file)
@@ -209,89 +209,20 @@ static struct kobj_type dump_ktype = {
        .default_attrs = dump_default_attrs,
 };
 
-static void free_dump_sg_list(struct opal_sg_list *list)
-{
-       struct opal_sg_list *sg1;
-       while (list) {
-               sg1 = list->next;
-               kfree(list);
-               list = sg1;
-       }
-       list = NULL;
-}
-
-static struct opal_sg_list *dump_data_to_sglist(struct dump_obj *dump)
-{
-       struct opal_sg_list *sg1, *list = NULL;
-       void *addr;
-       int64_t size;
-
-       addr = dump->buffer;
-       size = dump->size;
-
-       sg1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
-       if (!sg1)
-               goto nomem;
-
-       list = sg1;
-       sg1->num_entries = 0;
-       while (size > 0) {
-               /* Translate virtual address to physical address */
-               sg1->entry[sg1->num_entries].data =
-                       (void *)(vmalloc_to_pfn(addr) << PAGE_SHIFT);
-
-               if (size > PAGE_SIZE)
-                       sg1->entry[sg1->num_entries].length = PAGE_SIZE;
-               else
-                       sg1->entry[sg1->num_entries].length = size;
-
-               sg1->num_entries++;
-               if (sg1->num_entries >= SG_ENTRIES_PER_NODE) {
-                       sg1->next = kzalloc(PAGE_SIZE, GFP_KERNEL);
-                       if (!sg1->next)
-                               goto nomem;
-
-                       sg1 = sg1->next;
-                       sg1->num_entries = 0;
-               }
-               addr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-       return list;
-
-nomem:
-       pr_err("%s : Failed to allocate memory\n", __func__);
-       free_dump_sg_list(list);
-       return NULL;
-}
-
-static void sglist_to_phy_addr(struct opal_sg_list *list)
-{
-       struct opal_sg_list *sg, *next;
-
-       for (sg = list; sg; sg = next) {
-               next = sg->next;
-               /* Don't translate NULL pointer for last entry */
-               if (sg->next)
-                       sg->next = (struct opal_sg_list *)__pa(sg->next);
-               else
-                       sg->next = NULL;
-
-               /* Convert num_entries to length */
-               sg->num_entries =
-                       sg->num_entries * sizeof(struct opal_sg_entry) + 16;
-       }
-}
-
-static int64_t dump_read_info(uint32_t *id, uint32_t *size, uint32_t *type)
+static int64_t dump_read_info(uint32_t *dump_id, uint32_t *dump_size, uint32_t *dump_type)
 {
+       __be32 id, size, type;
        int rc;
-       *type = 0xffffffff;
 
-       rc = opal_dump_info2(id, size, type);
+       type = cpu_to_be32(0xffffffff);
 
+       rc = opal_dump_info2(&id, &size, &type);
        if (rc == OPAL_PARAMETER)
-               rc = opal_dump_info(id, size);
+               rc = opal_dump_info(&id, &size);
+
+       *dump_id = be32_to_cpu(id);
+       *dump_size = be32_to_cpu(size);
+       *dump_type = be32_to_cpu(type);
 
        if (rc)
                pr_warn("%s: Failed to get dump info (%d)\n",
@@ -314,15 +245,12 @@ static int64_t dump_read_data(struct dump_obj *dump)
        }
 
        /* Generate SG list */
-       list = dump_data_to_sglist(dump);
+       list = opal_vmalloc_to_sg_list(dump->buffer, dump->size);
        if (!list) {
                rc = -ENOMEM;
                goto out;
        }
 
-       /* Translate sg list addr to real address */
-       sglist_to_phy_addr(list);
-
        /* First entry address */
        addr = __pa(list);
 
@@ -341,7 +269,7 @@ static int64_t dump_read_data(struct dump_obj *dump)
                        __func__, dump->id);
 
        /* Free SG list */
-       free_dump_sg_list(list);
+       opal_free_sg_list(list);
 
 out:
        return rc;
index ef7bc2a..10268c4 100644 (file)
@@ -238,18 +238,25 @@ static struct elog_obj *create_elog_obj(uint64_t id, size_t size, uint64_t type)
 
 static void elog_work_fn(struct work_struct *work)
 {
-       size_t elog_size;
+       __be64 size;
+       __be64 id;
+       __be64 type;
+       uint64_t elog_size;
        uint64_t log_id;
        uint64_t elog_type;
        int rc;
        char name[2+16+1];
 
-       rc = opal_get_elog_size(&log_id, &elog_size, &elog_type);
+       rc = opal_get_elog_size(&id, &size, &type);
        if (rc != OPAL_SUCCESS) {
                pr_err("ELOG: Opal log read failed\n");
                return;
        }
 
+       elog_size = be64_to_cpu(size);
+       log_id = be64_to_cpu(id);
+       elog_type = be64_to_cpu(type);
+
        BUG_ON(elog_size > OPAL_MAX_ERRLOG_SIZE);
 
        if (elog_size >= OPAL_MAX_ERRLOG_SIZE)
index 714ef97..dc487ff 100644 (file)
@@ -79,9 +79,6 @@
 /* XXX: Assume candidate image size is <= 1GB */
 #define MAX_IMAGE_SIZE 0x40000000
 
-/* Flash sg list version */
-#define SG_LIST_VERSION (1UL)
-
 /* Image status */
 enum {
        IMAGE_INVALID,
@@ -131,11 +128,15 @@ static DEFINE_MUTEX(image_data_mutex);
  */
 static inline void opal_flash_validate(void)
 {
-       struct validate_flash_t *args_buf = &validate_flash_data;
+       long ret;
+       void *buf = validate_flash_data.buf;
+       __be32 size, result;
 
-       args_buf->status = opal_validate_flash(__pa(args_buf->buf),
-                                              &(args_buf->buf_size),
-                                              &(args_buf->result));
+       ret = opal_validate_flash(__pa(buf), &size, &result);
+
+       validate_flash_data.status = ret;
+       validate_flash_data.buf_size = be32_to_cpu(size);
+       validate_flash_data.result = be32_to_cpu(result);
 }
 
 /*
@@ -267,94 +268,12 @@ static ssize_t manage_store(struct kobject *kobj,
        return count;
 }
 
-/*
- * Free sg list
- */
-static void free_sg_list(struct opal_sg_list *list)
-{
-       struct opal_sg_list *sg1;
-       while (list) {
-               sg1 = list->next;
-               kfree(list);
-               list = sg1;
-       }
-       list = NULL;
-}
-
-/*
- * Build candidate image scatter gather list
- *
- * list format:
- *   -----------------------------------
- *  |  VER (8) | Entry length in bytes  |
- *   -----------------------------------
- *  |  Pointer to next entry            |
- *   -----------------------------------
- *  |  Address of memory area 1         |
- *   -----------------------------------
- *  |  Length of memory area 1          |
- *   -----------------------------------
- *  |   .........                       |
- *   -----------------------------------
- *  |   .........                       |
- *   -----------------------------------
- *  |  Address of memory area N         |
- *   -----------------------------------
- *  |  Length of memory area N          |
- *   -----------------------------------
- */
-static struct opal_sg_list *image_data_to_sglist(void)
-{
-       struct opal_sg_list *sg1, *list = NULL;
-       void *addr;
-       int size;
-
-       addr = image_data.data;
-       size = image_data.size;
-
-       sg1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
-       if (!sg1)
-               return NULL;
-
-       list = sg1;
-       sg1->num_entries = 0;
-       while (size > 0) {
-               /* Translate virtual address to physical address */
-               sg1->entry[sg1->num_entries].data =
-                       (void *)(vmalloc_to_pfn(addr) << PAGE_SHIFT);
-
-               if (size > PAGE_SIZE)
-                       sg1->entry[sg1->num_entries].length = PAGE_SIZE;
-               else
-                       sg1->entry[sg1->num_entries].length = size;
-
-               sg1->num_entries++;
-               if (sg1->num_entries >= SG_ENTRIES_PER_NODE) {
-                       sg1->next = kzalloc(PAGE_SIZE, GFP_KERNEL);
-                       if (!sg1->next) {
-                               pr_err("%s : Failed to allocate memory\n",
-                                      __func__);
-                               goto nomem;
-                       }
-
-                       sg1 = sg1->next;
-                       sg1->num_entries = 0;
-               }
-               addr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-       return list;
-nomem:
-       free_sg_list(list);
-       return NULL;
-}
-
 /*
  * OPAL update flash
  */
 static int opal_flash_update(int op)
 {
-       struct opal_sg_list *sg, *list, *next;
+       struct opal_sg_list *list;
        unsigned long addr;
        int64_t rc = OPAL_PARAMETER;
 
@@ -364,30 +283,13 @@ static int opal_flash_update(int op)
                goto flash;
        }
 
-       list = image_data_to_sglist();
+       list = opal_vmalloc_to_sg_list(image_data.data, image_data.size);
        if (!list)
                goto invalid_img;
 
        /* First entry address */
        addr = __pa(list);
 
-       /* Translate sg list address to absolute */
-       for (sg = list; sg; sg = next) {
-               next = sg->next;
-               /* Don't translate NULL pointer for last entry */
-               if (sg->next)
-                       sg->next = (struct opal_sg_list *)__pa(sg->next);
-               else
-                       sg->next = NULL;
-
-               /*
-                * Convert num_entries to version/length format
-                * to satisfy OPAL.
-                */
-               sg->num_entries = (SG_LIST_VERSION << 56) |
-                       (sg->num_entries * sizeof(struct opal_sg_entry) + 16);
-       }
-
        pr_alert("FLASH: Image is %u bytes\n", image_data.size);
        pr_alert("FLASH: Image update requested\n");
        pr_alert("FLASH: Image will be updated during system reboot\n");
index 6b61472..d202f9b 100644 (file)
@@ -39,10 +39,11 @@ struct param_attr {
        struct kobj_attribute kobj_attr;
 };
 
-static int opal_get_sys_param(u32 param_id, u32 length, void *buffer)
+static ssize_t opal_get_sys_param(u32 param_id, u32 length, void *buffer)
 {
        struct opal_msg msg;
-       int ret, token;
+       ssize_t ret;
+       int token;
 
        token = opal_async_get_token_interruptible();
        if (token < 0) {
@@ -59,7 +60,7 @@ static int opal_get_sys_param(u32 param_id, u32 length, void *buffer)
 
        ret = opal_async_wait_response(token, &msg);
        if (ret) {
-               pr_err("%s: Failed to wait for the async response, %d\n",
+               pr_err("%s: Failed to wait for the async response, %zd\n",
                                __func__, ret);
                goto out_token;
        }
@@ -111,7 +112,7 @@ static ssize_t sys_param_show(struct kobject *kobj,
 {
        struct param_attr *attr = container_of(kobj_attr, struct param_attr,
                        kobj_attr);
-       int ret;
+       ssize_t ret;
 
        mutex_lock(&opal_sysparam_mutex);
        ret = opal_get_sys_param(attr->param_id, attr->param_size,
@@ -121,9 +122,10 @@ static ssize_t sys_param_show(struct kobject *kobj,
 
        memcpy(buf, param_data_buf, attr->param_size);
 
+       ret = attr->param_size;
 out:
        mutex_unlock(&opal_sysparam_mutex);
-       return ret ? ret : attr->param_size;
+       return ret;
 }
 
 static ssize_t sys_param_store(struct kobject *kobj,
@@ -131,14 +133,20 @@ static ssize_t sys_param_store(struct kobject *kobj,
 {
        struct param_attr *attr = container_of(kobj_attr, struct param_attr,
                        kobj_attr);
-       int ret;
+       ssize_t ret;
+
+        /* MAX_PARAM_DATA_LEN is sizeof(param_data_buf) */
+        if (count > MAX_PARAM_DATA_LEN)
+                count = MAX_PARAM_DATA_LEN;
 
        mutex_lock(&opal_sysparam_mutex);
        memcpy(param_data_buf, buf, count);
        ret = opal_set_sys_param(attr->param_id, attr->param_size,
                        param_data_buf);
        mutex_unlock(&opal_sysparam_mutex);
-       return ret ? ret : count;
+       if (!ret)
+               ret = count;
+       return ret;
 }
 
 void __init opal_sys_param_init(void)
@@ -214,13 +222,13 @@ void __init opal_sys_param_init(void)
        }
 
        if (of_property_read_u32_array(sysparam, "param-len", size, count)) {
-               pr_err("SYSPARAM: Missing propery param-len in the DT\n");
+               pr_err("SYSPARAM: Missing property param-len in the DT\n");
                goto out_free_perm;
        }
 
 
        if (of_property_read_u8_array(sysparam, "param-perm", perm, count)) {
-               pr_err("SYSPARAM: Missing propery param-perm in the DT\n");
+               pr_err("SYSPARAM: Missing property param-perm in the DT\n");
                goto out_free_perm;
        }
 
@@ -233,6 +241,12 @@ void __init opal_sys_param_init(void)
 
        /* For each of the parameters, populate the parameter attributes */
        for (i = 0; i < count; i++) {
+               if (size[i] > MAX_PARAM_DATA_LEN) {
+                       pr_warn("SYSPARAM: Not creating parameter %d as size "
+                               "exceeds buffer length\n", i);
+                       continue;
+               }
+
                sysfs_attr_init(&attr[i].kobj_attr.attr);
                attr[i].param_id = id[i];
                attr[i].param_size = size[i];
index 49d2f00..360ad80 100644 (file)
@@ -242,14 +242,14 @@ void opal_notifier_update_evt(uint64_t evt_mask,
 void opal_notifier_enable(void)
 {
        int64_t rc;
-       uint64_t evt = 0;
+       __be64 evt = 0;
 
        atomic_set(&opal_notifier_hold, 0);
 
        /* Process pending events */
        rc = opal_poll_events(&evt);
        if (rc == OPAL_SUCCESS && evt)
-               opal_do_notifier(evt);
+               opal_do_notifier(be64_to_cpu(evt));
 }
 
 void opal_notifier_disable(void)
@@ -529,7 +529,7 @@ static irqreturn_t opal_interrupt(int irq, void *data)
 
        opal_handle_interrupt(virq_to_hw(irq), &events);
 
-       opal_do_notifier(events);
+       opal_do_notifier(be64_to_cpu(events));
 
        return IRQ_HANDLED;
 }
@@ -638,3 +638,66 @@ void opal_shutdown(void)
 
 /* Export this so that test modules can use it */
 EXPORT_SYMBOL_GPL(opal_invalid_call);
+
+/* Convert a region of vmalloc memory to an opal sg list */
+struct opal_sg_list *opal_vmalloc_to_sg_list(void *vmalloc_addr,
+                                            unsigned long vmalloc_size)
+{
+       struct opal_sg_list *sg, *first = NULL;
+       unsigned long i = 0;
+
+       sg = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!sg)
+               goto nomem;
+
+       first = sg;
+
+       while (vmalloc_size > 0) {
+               uint64_t data = vmalloc_to_pfn(vmalloc_addr) << PAGE_SHIFT;
+               uint64_t length = min(vmalloc_size, PAGE_SIZE);
+
+               sg->entry[i].data = cpu_to_be64(data);
+               sg->entry[i].length = cpu_to_be64(length);
+               i++;
+
+               if (i >= SG_ENTRIES_PER_NODE) {
+                       struct opal_sg_list *next;
+
+                       next = kzalloc(PAGE_SIZE, GFP_KERNEL);
+                       if (!next)
+                               goto nomem;
+
+                       sg->length = cpu_to_be64(
+                                       i * sizeof(struct opal_sg_entry) + 16);
+                       i = 0;
+                       sg->next = cpu_to_be64(__pa(next));
+                       sg = next;
+               }
+
+               vmalloc_addr += length;
+               vmalloc_size -= length;
+       }
+
+       sg->length = cpu_to_be64(i * sizeof(struct opal_sg_entry) + 16);
+
+       return first;
+
+nomem:
+       pr_err("%s : Failed to allocate memory\n", __func__);
+       opal_free_sg_list(first);
+       return NULL;
+}
+
+void opal_free_sg_list(struct opal_sg_list *sg)
+{
+       while (sg) {
+               uint64_t next = be64_to_cpu(sg->next);
+
+               kfree(sg);
+
+               if (next)
+                       sg = __va(next);
+               else
+                       sg = NULL;
+       }
+}
index 3b2b4fb..98824aa 100644 (file)
@@ -343,7 +343,6 @@ static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe)
                                pci_name(dev));
                        continue;
                }
-               pci_dev_get(dev);
                pdn->pcidev = dev;
                pdn->pe_number = pe->pe_number;
                pe->dma_weight += pnv_ioda_dma_weight(dev);
@@ -462,7 +461,7 @@ static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev
 
        pe = &phb->ioda.pe_array[pdn->pe_number];
        WARN_ON(get_dma_ops(&pdev->dev) != &dma_iommu_ops);
-       set_iommu_table_base_and_group(&pdev->dev, &pe->tce32_table);
+       set_iommu_table_base(&pdev->dev, &pe->tce32_table);
 }
 
 static int pnv_pci_ioda_dma_set_mask(struct pnv_phb *phb,
index 61cf8fa..8723d32 100644 (file)
@@ -162,18 +162,62 @@ static void pnv_shutdown(void)
 }
 
 #ifdef CONFIG_KEXEC
+static void pnv_kexec_wait_secondaries_down(void)
+{
+       int my_cpu, i, notified = -1;
+
+       my_cpu = get_cpu();
+
+       for_each_online_cpu(i) {
+               uint8_t status;
+               int64_t rc;
+
+               if (i == my_cpu)
+                       continue;
+
+               for (;;) {
+                       rc = opal_query_cpu_status(get_hard_smp_processor_id(i),
+                                                  &status);
+                       if (rc != OPAL_SUCCESS || status != OPAL_THREAD_STARTED)
+                               break;
+                       barrier();
+                       if (i != notified) {
+                               printk(KERN_INFO "kexec: waiting for cpu %d "
+                                      "(physical %d) to enter OPAL\n",
+                                      i, paca[i].hw_cpu_id);
+                               notified = i;
+                       }
+               }
+       }
+}
+
 static void pnv_kexec_cpu_down(int crash_shutdown, int secondary)
 {
        xics_kexec_teardown_cpu(secondary);
 
-       /* Return secondary CPUs to firmware on OPAL v3 */
-       if (firmware_has_feature(FW_FEATURE_OPALv3) && secondary) {
+       /* On OPAL v3, we return all CPUs to firmware */
+
+       if (!firmware_has_feature(FW_FEATURE_OPALv3))
+               return;
+
+       if (secondary) {
+               /* Return secondary CPUs to firmware on OPAL v3 */
                mb();
                get_paca()->kexec_state = KEXEC_STATE_REAL_MODE;
                mb();
 
                /* Return the CPU to OPAL */
                opal_return_cpu();
+       } else if (crash_shutdown) {
+               /*
+                * On crash, we don't wait for secondaries to go
+                * down as they might be unreachable or hung, so
+                * instead we just wait a bit and move on.
+                */
+               mdelay(1);
+       } else {
+               /* Primary waits for the secondaries to have reached OPAL */
+               pnv_kexec_wait_secondaries_down();
        }
 }
 #endif /* CONFIG_KEXEC */
index 908672b..bf5fcd4 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/cputhreads.h>
 #include <asm/xics.h>
 #include <asm/opal.h>
+#include <asm/runlatch.h>
 
 #include "powernv.h"
 
@@ -156,7 +157,9 @@ static void pnv_smp_cpu_kill_self(void)
         */
        mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1);
        while (!generic_check_cpu_restart(cpu)) {
+               ppc64_runlatch_off();
                power7_nap();
+               ppc64_runlatch_on();
                if (!generic_check_cpu_restart(cpu)) {
                        DBG("CPU%d Unexpected exit while offline !\n", cpu);
                        /* We may be getting an IPI, so we re-enable
index 9b8e050..20d6297 100644 (file)
@@ -88,13 +88,14 @@ void set_default_offline_state(int cpu)
 
 static void rtas_stop_self(void)
 {
-       struct rtas_args args = {
-               .token = cpu_to_be32(rtas_stop_self_token),
+       static struct rtas_args args = {
                .nargs = 0,
                .nret = 1,
                .rets = &args.args[0],
        };
 
+       args.token = cpu_to_be32(rtas_stop_self_token);
+
        local_irq_disable();
 
        BUG_ON(rtas_stop_self_token == RTAS_UNKNOWN_SERVICE);
index 573b488..7f75c94 100644 (file)
@@ -100,10 +100,10 @@ static int pseries_remove_memblock(unsigned long base, unsigned int memblock_siz
 
        start_pfn = base >> PAGE_SHIFT;
 
-       if (!pfn_valid(start_pfn)) {
-               memblock_remove(base, memblock_size);
-               return 0;
-       }
+       lock_device_hotplug();
+
+       if (!pfn_valid(start_pfn))
+               goto out;
 
        block_sz = memory_block_size_bytes();
        sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
@@ -114,8 +114,10 @@ static int pseries_remove_memblock(unsigned long base, unsigned int memblock_siz
                base += MIN_MEMORY_BLOCK_SIZE;
        }
 
+out:
        /* Update memory regions for memory remove */
        memblock_remove(base, memblock_size);
+       unlock_device_hotplug();
        return 0;
 }
 
index 64603a1..4914fd3 100644 (file)
@@ -1058,7 +1058,7 @@ static int __init apm821xx_pciex_core_init(struct device_node *np)
        return 1;
 }
 
-static int apm821xx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init apm821xx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
 {
        u32 val;
 
index cf3c008..23223cd 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 0a5aac8..7acb77f 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 b3ecb8f..9ae6664 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 9c36dc3..e9f8fa9 100644 (file)
@@ -276,7 +276,6 @@ static void bpf_jit_noleaks(struct bpf_jit *jit, struct sock_filter *filter)
        case BPF_S_LD_W_IND:
        case BPF_S_LD_H_IND:
        case BPF_S_LD_B_IND:
-       case BPF_S_LDX_B_MSH:
        case BPF_S_LD_IMM:
        case BPF_S_LD_MEM:
        case BPF_S_MISC_TXA:
@@ -812,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 0f9e945..1a49ffd 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 2230f80..90916f9 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 26b706a..452f04f 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 542e96a..605d492 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 6479256..3370945 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 9781048..745a363 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 f7c72b6..d066eb1 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 a364000..7f41d40 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 3c1a7cb..35ab8b6 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 2c20ad6..30eee6e 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 69bb818..4ced3fc 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 c4d3da6..1aed043 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 eafbc65..ed3c969 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 b12cb5e..b89aba2 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 f5d506f..fe19b81 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 d1b7c37..33f71b0 100644 (file)
@@ -79,11 +79,14 @@ else
         UTS_MACHINE := x86_64
         CHECKFLAGS += -D__x86_64__ -m64
 
+        biarch := -m64
         KBUILD_AFLAGS += -m64
         KBUILD_CFLAGS += -m64
 
         # Don't autogenerate traditional x87, MMX or SSE instructions
-        KBUILD_CFLAGS += -mno-mmx -mno-sse -mno-80387 -mno-fp-ret-in-387
+        KBUILD_CFLAGS += -mno-mmx -mno-sse
+        KBUILD_CFLAGS += $(call cc-option,-mno-80387)
+        KBUILD_CFLAGS += $(call cc-option,-mno-fp-ret-in-387)
 
        # Use -mpreferred-stack-boundary=3 if supported.
        KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=3)
index abb9eba..dbe8dd2 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 1768461..57ab74d 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 0ca9a5c..84c2234 100644 (file)
@@ -375,8 +375,7 @@ xloadflags:
 # define XLF0 0
 #endif
 
-#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_X86_64) && \
-       !defined(CONFIG_EFI_MIXED)
+#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_X86_64)
    /* kernel/boot_param/ramdisk could be loaded above 4g */
 # define XLF1 XLF_CAN_BE_LOADED_ABOVE_4G
 #else
index b18df57..36f7125 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 a809121..68c0539 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 8de6d9c..6782051 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 c827ace..fcf2b3a 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 3a2ae4c..3136820 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 6ad4658..992060e 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;
 
@@ -3425,6 +3425,11 @@ int get_nr_irqs_gsi(void)
        return nr_irqs_gsi;
 }
 
+unsigned int arch_dynirq_lower_bound(unsigned int from)
+{
+       return from < nr_irqs_gsi ? nr_irqs_gsi : from;
+}
+
 int __init arch_probe_nr_irqs(void)
 {
        int nr;
index a135239..a4bcbac 100644 (file)
@@ -1221,6 +1221,17 @@ static void dbg_restore_debug_regs(void)
 #define dbg_restore_debug_regs()
 #endif /* ! CONFIG_KGDB */
 
+static void wait_for_master_cpu(int cpu)
+{
+       /*
+        * wait for ACK from master CPU before continuing
+        * with AP initialization
+        */
+       WARN_ON(cpumask_test_and_set_cpu(cpu, cpu_initialized_mask));
+       while (!cpumask_test_cpu(cpu, cpu_callout_mask))
+               cpu_relax();
+}
+
 /*
  * cpu_init() initializes state that is per-CPU. Some data is already
  * initialized (naturally) in the bootstrap process, such as the GDT
@@ -1236,16 +1247,17 @@ void cpu_init(void)
        struct task_struct *me;
        struct tss_struct *t;
        unsigned long v;
-       int cpu;
+       int cpu = stack_smp_processor_id();
        int i;
 
+       wait_for_master_cpu(cpu);
+
        /*
         * Load microcode on this cpu if a valid microcode is available.
         * This is early microcode loading procedure.
         */
        load_ucode_ap();
 
-       cpu = stack_smp_processor_id();
        t = &per_cpu(init_tss, cpu);
        oist = &per_cpu(orig_ist, cpu);
 
@@ -1257,9 +1269,6 @@ void cpu_init(void)
 
        me = current;
 
-       if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask))
-               panic("CPU#%d already initialized!\n", cpu);
-
        pr_debug("Initializing CPU#%d\n", cpu);
 
        clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
@@ -1336,13 +1345,9 @@ void cpu_init(void)
        struct tss_struct *t = &per_cpu(init_tss, cpu);
        struct thread_struct *thread = &curr->thread;
 
-       show_ucode_info_early();
+       wait_for_master_cpu(cpu);
 
-       if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)) {
-               printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
-               for (;;)
-                       local_irq_enable();
-       }
+       show_ucode_info_early();
 
        printk(KERN_INFO "Initializing CPU#%d\n", cpu);
 
index d921b7e..36a1bb6 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 fe6b1c8..7245980 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 aa333d9..adb02aa 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 7c87424..619f769 100644 (file)
@@ -543,7 +543,8 @@ static int rapl_cpu_prepare(int cpu)
        if (phys_id < 0)
                return -1;
 
-       if (!rdmsrl_safe(MSR_RAPL_POWER_UNIT, &msr_rapl_power_unit_bits))
+       /* protect rdmsrl() to handle virtualization */
+       if (rdmsrl_safe(MSR_RAPL_POWER_UNIT, &msr_rapl_power_unit_bits))
                return -1;
 
        pmu = kzalloc_node(sizeof(*pmu), GFP_KERNEL, cpu_to_node(cpu));
index 384df51..136ac74 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 6e2537c..6cda0ba 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 c61a14a..d6c1b98 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 85126cc..068054f 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 8d80ae0..4177bfb 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 283a76a..11ccfb0 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/idle.h>
 #include <asm/mce.h>
 #include <asm/hw_irq.h>
+#include <asm/desc.h>
 
 #define CREATE_TRACE_POINTS
 #include <asm/trace/irq_vectors.h>
@@ -334,10 +335,17 @@ int check_irq_vectors_for_cpu_disable(void)
        for_each_online_cpu(cpu) {
                if (cpu == this_cpu)
                        continue;
-               for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS;
-                    vector++) {
-                       if (per_cpu(vector_irq, cpu)[vector] < 0)
-                               count++;
+               /*
+                * We scan from FIRST_EXTERNAL_VECTOR to first system
+                * vector. If the vector is marked in the used vectors
+                * bitmap or an irq is assigned to it, we don't count
+                * it as available.
+                */
+               for (vector = FIRST_EXTERNAL_VECTOR;
+                    vector < first_system_vector; vector++) {
+                       if (!test_bit(vector, used_vectors) &&
+                           per_cpu(vector_irq, cpu)[vector] < 0)
+                                       count++;
                }
        }
 
index af1d14a..dcbbaa1 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 9c0280f..898d077 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 3399d3a..52b1157 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 7c3a5a6..be8e1bd 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 3482693..bc52fac 100644 (file)
@@ -111,7 +111,6 @@ atomic_t init_deasserted;
 static void smp_callin(void)
 {
        int cpuid, phys_id;
-       unsigned long timeout;
 
        /*
         * If waken up by an INIT in an 82489DX configuration
@@ -130,37 +129,6 @@ static void smp_callin(void)
         * (This works even if the APIC is not enabled.)
         */
        phys_id = read_apic_id();
-       if (cpumask_test_cpu(cpuid, cpu_callin_mask)) {
-               panic("%s: phys CPU#%d, CPU#%d already present??\n", __func__,
-                                       phys_id, cpuid);
-       }
-       pr_debug("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
-
-       /*
-        * STARTUP IPIs are fragile beasts as they might sometimes
-        * trigger some glue motherboard logic. Complete APIC bus
-        * silence for 1 second, this overestimates the time the
-        * boot CPU is spending to send the up to 2 STARTUP IPIs
-        * by a factor of two. This should be enough.
-        */
-
-       /*
-        * Waiting 2s total for startup (udelay is not yet working)
-        */
-       timeout = jiffies + 2*HZ;
-       while (time_before(jiffies, timeout)) {
-               /*
-                * Has the boot CPU finished it's STARTUP sequence?
-                */
-               if (cpumask_test_cpu(cpuid, cpu_callout_mask))
-                       break;
-               cpu_relax();
-       }
-
-       if (!time_before(jiffies, timeout)) {
-               panic("%s: CPU%d started up but did not get a callout!\n",
-                     __func__, cpuid);
-       }
 
        /*
         * the boot CPU has finished the init stage and is spinning
@@ -750,8 +718,8 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
        unsigned long start_ip = real_mode_header->trampoline_start;
 
        unsigned long boot_error = 0;
-       int timeout;
        int cpu0_nmi_registered = 0;
+       unsigned long timeout;
 
        /* Just in case we booted with a single CPU. */
        alternatives_enable_smp();
@@ -798,6 +766,15 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
                }
        }
 
+       /*
+        * AP might wait on cpu_callout_mask in cpu_init() with
+        * cpu_initialized_mask set if previous attempt to online
+        * it timed-out. Clear cpu_initialized_mask so that after
+        * INIT/SIPI it could start with a clean state.
+        */
+       cpumask_clear_cpu(cpu, cpu_initialized_mask);
+       smp_mb();
+
        /*
         * Wake up a CPU in difference cases:
         * - Use the method in the APIC driver if it's defined
@@ -810,58 +787,41 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
                boot_error = wakeup_cpu_via_init_nmi(cpu, start_ip, apicid,
                                                     &cpu0_nmi_registered);
 
+
        if (!boot_error) {
                /*
-                * allow APs to start initializing.
+                * Wait 10s total for a response from AP
                 */
-               pr_debug("Before Callout %d\n", cpu);
-               cpumask_set_cpu(cpu, cpu_callout_mask);
-               pr_debug("After Callout %d\n", cpu);
+               boot_error = -1;
+               timeout = jiffies + 10*HZ;
+               while (time_before(jiffies, timeout)) {
+                       if (cpumask_test_cpu(cpu, cpu_initialized_mask)) {
+                               /*
+                                * Tell AP to proceed with initialization
+                                */
+                               cpumask_set_cpu(cpu, cpu_callout_mask);
+                               boot_error = 0;
+                               break;
+                       }
+                       udelay(100);
+                       schedule();
+               }
+       }
 
+       if (!boot_error) {
                /*
-                * Wait 5s total for a response
+                * Wait till AP completes initial initialization
                 */
-               for (timeout = 0; timeout < 50000; timeout++) {
-                       if (cpumask_test_cpu(cpu, cpu_callin_mask))
-                               break;  /* It has booted */
-                       udelay(100);
+               while (!cpumask_test_cpu(cpu, cpu_callin_mask)) {
                        /*
                         * Allow other tasks to run while we wait for the
                         * AP to come online. This also gives a chance
                         * for the MTRR work(triggered by the AP coming online)
                         * to be completed in the stop machine context.
                         */
+                       udelay(100);
                        schedule();
                }
-
-               if (cpumask_test_cpu(cpu, cpu_callin_mask)) {
-                       print_cpu_msr(&cpu_data(cpu));
-                       pr_debug("CPU%d: has booted.\n", cpu);
-               } else {
-                       boot_error = 1;
-                       if (*trampoline_status == 0xA5A5A5A5)
-                               /* trampoline started but...? */
-                               pr_err("CPU%d: Stuck ??\n", cpu);
-                       else
-                               /* trampoline code not run */
-                               pr_err("CPU%d: Not responding\n", cpu);
-                       if (apic->inquire_remote_apic)
-                               apic->inquire_remote_apic(apicid);
-               }
-       }
-
-       if (boot_error) {
-               /* Try to put things back the way they were before ... */
-               numa_remove_cpu(cpu); /* was set by numa_add_cpu */
-
-               /* was set by do_boot_cpu() */
-               cpumask_clear_cpu(cpu, cpu_callout_mask);
-
-               /* was set by cpu_init() */
-               cpumask_clear_cpu(cpu, cpu_initialized_mask);
-
-               set_cpu_present(cpu, false);
-               per_cpu(x86_cpu_to_apicid, cpu) = BAD_APICID;
        }
 
        /* mark "stuck" area as not stuck */
@@ -921,7 +881,7 @@ int native_cpu_up(unsigned int cpu, struct task_struct *tidle)
 
        err = do_boot_cpu(apicid, cpu, tidle);
        if (err) {
-               pr_debug("do_boot_cpu failed %d\n", err);
+               pr_err("do_boot_cpu failed(%d) to wakeup CPU#%u\n", err, cpu);
                return -EIO;
        }
 
index 57409f6..f73b5d4 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 f6584a9..b99b9ad 100644 (file)
@@ -26,6 +26,9 @@
 
 #define TOPOLOGY_REGISTER_OFFSET 0x10
 
+/* Flag below is initialized once during vSMP PCI initialization. */
+static int irq_routing_comply = 1;
+
 #if defined CONFIG_PCI && defined CONFIG_PARAVIRT
 /*
  * Interrupt control on vSMPowered systems:
@@ -33,7 +36,7 @@
  * and vice versa.
  */
 
-asmlinkage unsigned long vsmp_save_fl(void)
+asmlinkage __visible unsigned long vsmp_save_fl(void)
 {
        unsigned long flags = native_save_fl();
 
@@ -53,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();
 
@@ -61,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();
 
@@ -101,6 +104,10 @@ static void __init set_vsmp_pv_ops(void)
 #ifdef CONFIG_SMP
        if (cap & ctl & BIT(8)) {
                ctl &= ~BIT(8);
+
+               /* Interrupt routing set to ignore */
+               irq_routing_comply = 0;
+
 #ifdef CONFIG_PROC_FS
                /* Don't let users change irq affinity via procfs */
                no_irq_affinity = 1;
@@ -218,7 +225,9 @@ static void vsmp_apic_post_init(void)
 {
        /* need to update phys_pkg_id */
        apic->phys_pkg_id = apicid_phys_pkg_id;
-       apic->vector_allocation_domain = fill_vector_allocation_domain;
+
+       if (!irq_routing_comply)
+               apic->vector_allocation_domain = fill_vector_allocation_domain;
 }
 
 void __init vsmp_init(void)
index f9c6e56..9531fbb 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 1f68c58..138ceff 100644 (file)
@@ -503,7 +503,7 @@ static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
                                [number##_HIGH] = VMCS12_OFFSET(name)+4
 
 
-static const unsigned long shadow_read_only_fields[] = {
+static unsigned long shadow_read_only_fields[] = {
        /*
         * We do NOT shadow fields that are modified when L0
         * traps and emulates any vmx instruction (e.g. VMPTRLD,
@@ -526,10 +526,10 @@ static const unsigned long shadow_read_only_fields[] = {
        GUEST_LINEAR_ADDRESS,
        GUEST_PHYSICAL_ADDRESS
 };
-static const int max_shadow_read_only_fields =
+static int max_shadow_read_only_fields =
        ARRAY_SIZE(shadow_read_only_fields);
 
-static const unsigned long shadow_read_write_fields[] = {
+static unsigned long shadow_read_write_fields[] = {
        GUEST_RIP,
        GUEST_RSP,
        GUEST_CR0,
@@ -558,7 +558,7 @@ static const unsigned long shadow_read_write_fields[] = {
        HOST_FS_SELECTOR,
        HOST_GS_SELECTOR
 };
-static const int max_shadow_read_write_fields =
+static int max_shadow_read_write_fields =
        ARRAY_SIZE(shadow_read_write_fields);
 
 static const unsigned short vmcs_field_to_offset_table[] = {
@@ -3009,6 +3009,41 @@ static void free_kvm_area(void)
        }
 }
 
+static void init_vmcs_shadow_fields(void)
+{
+       int i, j;
+
+       /* No checks for read only fields yet */
+
+       for (i = j = 0; i < max_shadow_read_write_fields; i++) {
+               switch (shadow_read_write_fields[i]) {
+               case GUEST_BNDCFGS:
+                       if (!vmx_mpx_supported())
+                               continue;
+                       break;
+               default:
+                       break;
+               }
+
+               if (j < i)
+                       shadow_read_write_fields[j] =
+                               shadow_read_write_fields[i];
+               j++;
+       }
+       max_shadow_read_write_fields = j;
+
+       /* shadowed fields guest access without vmexit */
+       for (i = 0; i < max_shadow_read_write_fields; i++) {
+               clear_bit(shadow_read_write_fields[i],
+                         vmx_vmwrite_bitmap);
+               clear_bit(shadow_read_write_fields[i],
+                         vmx_vmread_bitmap);
+       }
+       for (i = 0; i < max_shadow_read_only_fields; i++)
+               clear_bit(shadow_read_only_fields[i],
+                         vmx_vmread_bitmap);
+}
+
 static __init int alloc_kvm_area(void)
 {
        int cpu;
@@ -3039,6 +3074,8 @@ static __init int hardware_setup(void)
                enable_vpid = 0;
        if (!cpu_has_vmx_shadow_vmcs())
                enable_shadow_vmcs = 0;
+       if (enable_shadow_vmcs)
+               init_vmcs_shadow_fields();
 
        if (!cpu_has_vmx_ept() ||
            !cpu_has_vmx_ept_4levels()) {
@@ -7741,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;
@@ -7778,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;
@@ -8803,14 +8843,6 @@ static int __init vmx_init(void)
 
        memset(vmx_vmread_bitmap, 0xff, PAGE_SIZE);
        memset(vmx_vmwrite_bitmap, 0xff, PAGE_SIZE);
-       /* shadowed read/write fields */
-       for (i = 0; i < max_shadow_read_write_fields; i++) {
-               clear_bit(shadow_read_write_fields[i], vmx_vmwrite_bitmap);
-               clear_bit(shadow_read_write_fields[i], vmx_vmread_bitmap);
-       }
-       /* shadowed read only fields */
-       for (i = 0; i < max_shadow_read_only_fields; i++)
-               clear_bit(shadow_read_only_fields[i], vmx_vmread_bitmap);
 
        /*
         * Allow direct access to the PC debug port (it is often used for I/O
index 8b8fc0b..20316c6 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 ad1fb5f..aae9413 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 db9db44..4362373 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 a544908..9e6545f 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 dc01773..6d5663a 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 81b506d..5241421 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 3781dd3..4d36932 100644 (file)
@@ -919,6 +919,9 @@ static void __init save_runtime_map(void)
        void *tmp, *p, *q = NULL;
        int count = 0;
 
+       if (efi_enabled(EFI_OLD_MEMMAP))
+               return;
+
        for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
                md = p;
 
index ff0174d..a9acde7 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 304fca2..35e2bb6 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 0034898..310c5f0 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
 
 /*
@@ -154,6 +155,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
        unsigned long addr;
        int ret = 0;
        struct vm_area_struct *vma;
+       static struct page *no_pages[] = {NULL};
 
 #ifdef CONFIG_X86_X32_ABI
        if (test_thread_flag(TIF_X32))
@@ -192,7 +194,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
                        addr -  VDSO_OFFSET(VDSO_PREV_PAGES),
                        VDSO_OFFSET(VDSO_PREV_PAGES),
                        VM_READ,
-                       NULL);
+                       no_pages);
 
        if (IS_ERR(vma)) {
                ret = PTR_ERR(vma);
@@ -249,6 +251,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 201d09a..c34bfc4 100644 (file)
@@ -1515,7 +1515,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 08f763d..a1207cb 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 02d6d29..3a617af 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 e5703c7..1d97203 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 6f9c10d..d1c621c 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 e7370b1..dec9178 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 23392c5..892aab3 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 80be151..2653ef5 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 2164462..4b0ca35 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 fc34274..06875fe 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 84fe931..9757bb7 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 aa8bd87..40b5a37 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 80b33ed..4d2872f 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 f0b646d..f54f78e 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 ba4c47f..63cbb86 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 aff108d..4224256 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 861203e..3429b48 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 ade6238..5ece856 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 d2369b7..b3e8929 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 f9bc879..b90555c 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 e4a4145..1039fb9 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 1512e41..43665d0 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 d05d81b..7183b6a 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 ab686b3..a34a228 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 0331f91..bce34af 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 2c01c1d..c67f6f5 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 dbfe49e..1d49503 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 c29c2c3..52c81c4 100644 (file)
@@ -170,6 +170,9 @@ static int acpi_processor_hotadd_init(struct acpi_processor *pr)
        acpi_status status;
        int ret;
 
+       if (pr->apic_id == -1)
+               return -ENODEV;
+
        status = acpi_evaluate_integer(pr->handle, "_STA", NULL, &sta);
        if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT))
                return -ENODEV;
@@ -260,10 +263,8 @@ static int acpi_processor_get_info(struct acpi_device *device)
        }
 
        apic_id = acpi_get_apicid(pr->handle, device_declaration, pr->acpi_id);
-       if (apic_id < 0) {
+       if (apic_id < 0)
                acpi_handle_debug(pr->handle, "failed to get CPU APIC ID.\n");
-               return -ENODEV;
-       }
        pr->apic_id = apic_id;
 
        cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id);
@@ -404,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 49bbc71..a08a448 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 a4702ee..9fb85f3 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 9a2c63b..6e7b2a1 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 afec452..3d8413d 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 d7d32c2..ad11ba4 100644 (file)
@@ -206,13 +206,13 @@ unlock:
        spin_unlock_irqrestore(&ec->lock, flags);
 }
 
-static int acpi_ec_sync_query(struct acpi_ec *ec);
+static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data);
 
 static int ec_check_sci_sync(struct acpi_ec *ec, u8 state)
 {
        if (state & ACPI_EC_FLAG_SCI) {
                if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
-                       return acpi_ec_sync_query(ec);
+                       return acpi_ec_sync_query(ec, NULL);
        }
        return 0;
 }
@@ -443,10 +443,8 @@ acpi_handle ec_get_handle(void)
 
 EXPORT_SYMBOL(ec_get_handle);
 
-static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 *data);
-
 /*
- * Clears stale _Q events that might have accumulated in the EC.
+ * Process _Q events that might have accumulated in the EC.
  * Run with locked ec mutex.
  */
 static void acpi_ec_clear(struct acpi_ec *ec)
@@ -455,7 +453,7 @@ static void acpi_ec_clear(struct acpi_ec *ec)
        u8 value = 0;
 
        for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) {
-               status = acpi_ec_query_unlocked(ec, &value);
+               status = acpi_ec_sync_query(ec, &value);
                if (status || !value)
                        break;
        }
@@ -582,13 +580,18 @@ static void acpi_ec_run(void *cxt)
        kfree(handler);
 }
 
-static int acpi_ec_sync_query(struct acpi_ec *ec)
+static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data)
 {
        u8 value = 0;
        int status;
        struct acpi_ec_query_handler *handler, *copy;
-       if ((status = acpi_ec_query_unlocked(ec, &value)))
+
+       status = acpi_ec_query_unlocked(ec, &value);
+       if (data)
+               *data = value;
+       if (status)
                return status;
+
        list_for_each_entry(handler, &ec->list, node) {
                if (value == handler->query_bit) {
                        /* have custom handler for this bit */
@@ -612,7 +615,7 @@ static void acpi_ec_gpe_query(void *ec_cxt)
        if (!ec)
                return;
        mutex_lock(&ec->mutex);
-       acpi_ec_sync_query(ec);
+       acpi_ec_sync_query(ec, NULL);
        mutex_unlock(&ec->mutex);
 }
 
index c1e31a4..25bbc55 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 8b6990e..f8bc5a7 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 c270604..0033faf 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 71e15b7..6070781 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 b5eb886..af63c75 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 497c7ab..8befeb6 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 6bd4f66..b986145 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 943cc8b..18d97d5 100644 (file)
@@ -4224,10 +4224,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "PIONEER DVD-RW  DVR-216D",   NULL,   ATA_HORKAGE_NOSETXFER },
 
        /* devices that don't properly handle queued TRIM commands */
-       { "Micron_M500*",               "MU0[1-4]*",    ATA_HORKAGE_NO_NCQ_TRIM, },
-       { "Crucial_CT???M500SSD*",      "MU0[1-4]*",    ATA_HORKAGE_NO_NCQ_TRIM, },
-       { "Micron_M550*",               NULL,           ATA_HORKAGE_NO_NCQ_TRIM, },
-       { "Crucial_CT???M550SSD*",      NULL,           ATA_HORKAGE_NO_NCQ_TRIM, },
+       { "Micron_M500*",               NULL,   ATA_HORKAGE_NO_NCQ_TRIM, },
+       { "Crucial_CT???M500SSD*",      NULL,   ATA_HORKAGE_NO_NCQ_TRIM, },
+       { "Micron_M550*",               NULL,   ATA_HORKAGE_NO_NCQ_TRIM, },
+       { "Crucial_CT???M550SSD*",      NULL,   ATA_HORKAGE_NO_NCQ_TRIM, },
 
        /*
         * Some WD SATA-I drives spin up and down erratically when the link
@@ -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 8986b9f..62ec61e 100644 (file)
@@ -52,6 +52,7 @@ static DEFINE_MUTEX(deferred_probe_mutex);
 static LIST_HEAD(deferred_probe_pending_list);
 static LIST_HEAD(deferred_probe_active_list);
 static struct workqueue_struct *deferred_wq;
+static atomic_t deferred_trigger_count = ATOMIC_INIT(0);
 
 /**
  * deferred_probe_work_func() - Retry probing devices in the active list.
@@ -135,6 +136,17 @@ static bool driver_deferred_probe_enable = false;
  * This functions moves all devices from the pending list to the active
  * list and schedules the deferred probe workqueue to process them.  It
  * should be called anytime a driver is successfully bound to a device.
+ *
+ * Note, there is a race condition in multi-threaded probe. In the case where
+ * more than one device is probing at the same time, it is possible for one
+ * probe to complete successfully while another is about to defer. If the second
+ * depends on the first, then it will get put on the pending list after the
+ * trigger event has already occured and will be stuck there.
+ *
+ * The atomic 'deferred_trigger_count' is used to determine if a successful
+ * trigger has occurred in the midst of probing a driver. If the trigger count
+ * changes in the midst of a probe, then deferred processing should be triggered
+ * again.
  */
 static void driver_deferred_probe_trigger(void)
 {
@@ -147,6 +159,7 @@ static void driver_deferred_probe_trigger(void)
         * into the active list so they can be retried by the workqueue
         */
        mutex_lock(&deferred_probe_mutex);
+       atomic_inc(&deferred_trigger_count);
        list_splice_tail_init(&deferred_probe_pending_list,
                              &deferred_probe_active_list);
        mutex_unlock(&deferred_probe_mutex);
@@ -265,6 +278,7 @@ static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);
 static int really_probe(struct device *dev, struct device_driver *drv)
 {
        int ret = 0;
+       int local_trigger_count = atomic_read(&deferred_trigger_count);
 
        atomic_inc(&probe_count);
        pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
@@ -310,6 +324,9 @@ probe_failed:
                /* Driver requested deferred probing */
                dev_info(dev, "Driver %s requests probe deferral\n", drv->name);
                driver_deferred_probe_add(dev);
+               /* Did a trigger occur while probing? Need to re-trigger if yes */
+               if (local_trigger_count != atomic_read(&deferred_trigger_count))
+                       driver_deferred_probe_trigger();
        } else if (ret != -ENODEV && ret != -ENXIO) {
                /* driver matched but the probe failed */
                printk(KERN_WARNING
index e714709..5b47210 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/string.h>
 #include <linux/platform_device.h>
 #include <linux/of_device.h>
+#include <linux/of_irq.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
@@ -87,7 +88,11 @@ int platform_get_irq(struct platform_device *dev, unsigned int num)
                return -ENXIO;
        return dev->archdata.irqs[num];
 #else
-       struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num);
+       struct resource *r;
+       if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node)
+               return of_irq_get(dev->dev.of_node, num);
+
+       r = platform_get_resource(dev, IORESOURCE_IRQ, num);
 
        return r ? r->start : -ENXIO;
 #endif
index 8f5565b..fa9bb74 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 6d8a87f..cb9b1f8 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 be571fe..a83b57e 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 f338b0c..a7dfbf9 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 293e2e0..00b7344 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 8121b4c..b297033 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 6b75713..102c50d 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 b3ea223..61dcc80 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 c7607fe..54a0652 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 e3d339e..db11a87 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 5e139ad..dee6909 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 ec22112..3fbee45 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 dff0373..7cf2c09 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 2e5810c..1f6324e 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 88dafb5..de6da95 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 35a960a..43db947 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 bca0a0b..a886702 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 0d20241..6aad8ab 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 a535c7b..4223912 100644 (file)
@@ -100,6 +100,8 @@ void __init vexpress_osc_of_setup(struct device_node *node)
        struct clk *clk;
        u32 range[2];
 
+       vexpress_sysreg_of_early_init();
+
        osc = kzalloc(sizeof(*osc), GFP_KERNEL);
        if (!osc)
                return;
index 57e823c..5163ec1 100644 (file)
@@ -66,6 +66,7 @@ static int arch_timer_ppi[MAX_TIMER_PPI];
 static struct clock_event_device __percpu *arch_timer_evt;
 
 static bool arch_timer_use_virtual = true;
+static bool arch_timer_c3stop;
 static bool arch_timer_mem_use_virtual;
 
 /*
@@ -263,7 +264,8 @@ static void __arch_timer_setup(unsigned type,
        clk->features = CLOCK_EVT_FEAT_ONESHOT;
 
        if (type == ARCH_CP15_TIMER) {
-               clk->features |= CLOCK_EVT_FEAT_C3STOP;
+               if (arch_timer_c3stop)
+                       clk->features |= CLOCK_EVT_FEAT_C3STOP;
                clk->name = "arch_sys_timer";
                clk->rating = 450;
                clk->cpumask = cpumask_of(smp_processor_id());
@@ -665,6 +667,8 @@ static void __init arch_timer_init(struct device_node *np)
                }
        }
 
+       arch_timer_c3stop = !of_property_read_bool(np, "always-on");
+
        arch_timer_register();
        arch_timer_common_init();
 }
index 00fdd11..a8d7ea1 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 b52e1c0..7f5374d 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 ca81809..7ce4421 100644 (file)
@@ -212,4 +212,9 @@ error_free:
        return ret;
 }
 
-CLOCKSOURCE_OF_DECLARE(zevio_timer, "lsi,zevio-timer", zevio_timer_add);
+static void __init zevio_timer_init(struct device_node *node)
+{
+       BUG_ON(zevio_timer_add(node));
+}
+
+CLOCKSOURCE_OF_DECLARE(zevio_timer, "lsi,zevio-timer", zevio_timer_init);
index 148d707..ccdd4c7 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 1bf6bba..09b9129 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 ba43991..e1c6433 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 0999673..db2e45b 100644 (file)
 #define BYT_RATIOS             0x66a
 #define BYT_VIDS               0x66b
 #define BYT_TURBO_RATIOS       0x66c
+#define BYT_TURBO_VIDS         0x66d
 
 
-#define FRAC_BITS 6
+#define FRAC_BITS 8
 #define int_tofp(X) ((int64_t)(X) << FRAC_BITS)
 #define fp_toint(X) ((X) >> FRAC_BITS)
-#define FP_ROUNDUP(X) ((X) += 1 << FRAC_BITS)
+
 
 static inline int32_t mul_fp(int32_t x, int32_t y)
 {
@@ -58,8 +59,8 @@ struct sample {
        int32_t core_pct_busy;
        u64 aperf;
        u64 mperf;
-       unsigned long long tsc;
        int freq;
+       ktime_t time;
 };
 
 struct pstate_data {
@@ -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;
 };
 
@@ -96,9 +98,9 @@ struct cpudata {
        struct vid_data vid;
        struct _pid pid;
 
+       ktime_t last_sample_time;
        u64     prev_aperf;
        u64     prev_mperf;
-       unsigned long long prev_tsc;
        struct sample sample;
 };
 
@@ -198,7 +200,10 @@ static signed int pid_calc(struct _pid *pid, int32_t busy)
        pid->last_err = fp_error;
 
        result = pterm + mul_fp(pid->integral, pid->i_gain) + dterm;
-
+       if (result >= 0)
+               result = result + (1 << (FRAC_BITS-1));
+       else
+               result = result - (1 << (FRAC_BITS-1));
        return (signed int)fp_toint(result);
 }
 
@@ -359,14 +364,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 +398,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 +410,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,58 +557,48 @@ 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,
                                        struct sample *sample)
 {
-       int32_t core_pct;
-       int32_t c0_pct;
+       int64_t core_pct;
+       int32_t rem;
 
-       core_pct = div_fp(int_tofp((sample->aperf)),
-                       int_tofp((sample->mperf)));
-       core_pct = mul_fp(core_pct, int_tofp(100));
-       FP_ROUNDUP(core_pct);
+       core_pct = int_tofp(sample->aperf) * int_tofp(100);
+       core_pct = div_u64_rem(core_pct, int_tofp(sample->mperf), &rem);
 
-       c0_pct = div_fp(int_tofp(sample->mperf), int_tofp(sample->tsc));
+       if ((rem << 1) >= int_tofp(sample->mperf))
+               core_pct += 1;
 
        sample->freq = fp_toint(
                mul_fp(int_tofp(cpu->pstate.max_pstate * 1000), core_pct));
 
-       sample->core_pct_busy = mul_fp(core_pct, c0_pct);
+       sample->core_pct_busy = (int32_t)core_pct;
 }
 
 static inline void intel_pstate_sample(struct cpudata *cpu)
 {
        u64 aperf, mperf;
-       unsigned long long tsc;
 
        rdmsrl(MSR_IA32_APERF, aperf);
        rdmsrl(MSR_IA32_MPERF, mperf);
-       tsc = native_read_tsc();
 
        aperf = aperf >> FRAC_BITS;
        mperf = mperf >> FRAC_BITS;
-       tsc = tsc >> FRAC_BITS;
 
+       cpu->last_sample_time = cpu->sample.time;
+       cpu->sample.time = ktime_get();
        cpu->sample.aperf = aperf;
        cpu->sample.mperf = mperf;
-       cpu->sample.tsc = tsc;
        cpu->sample.aperf -= cpu->prev_aperf;
        cpu->sample.mperf -= cpu->prev_mperf;
-       cpu->sample.tsc -= cpu->prev_tsc;
 
        intel_pstate_calc_busy(cpu, &cpu->sample);
 
        cpu->prev_aperf = aperf;
        cpu->prev_mperf = mperf;
-       cpu->prev_tsc = tsc;
 }
 
 static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
@@ -610,13 +612,25 @@ static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
 
 static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu)
 {
-       int32_t core_busy, max_pstate, current_pstate;
+       int32_t core_busy, max_pstate, current_pstate, sample_ratio;
+       u32 duration_us;
+       u32 sample_time;
 
        core_busy = cpu->sample.core_pct_busy;
        max_pstate = int_tofp(cpu->pstate.max_pstate);
        current_pstate = int_tofp(cpu->pstate.current_pstate);
        core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
-       return FP_ROUNDUP(core_busy);
+
+       sample_time = (pid_params.sample_rate_ms  * USEC_PER_MSEC);
+       duration_us = (u32) ktime_us_delta(cpu->sample.time,
+                                       cpu->last_sample_time);
+       if (duration_us > sample_time * 3) {
+               sample_ratio = div_fp(int_tofp(sample_time),
+                               int_tofp(duration_us));
+               core_busy = mul_fp(core_busy, sample_ratio);
+       }
+
+       return core_busy;
 }
 
 static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
@@ -695,11 +709,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 +719,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 d00e5d1..5c4369b 100644 (file)
@@ -242,7 +242,7 @@ static void do_powersaver(int cx_address, unsigned int mults_index,
  * Sets a new clock ratio.
  */
 
-static void longhaul_setstate(struct cpufreq_policy *policy,
+static int longhaul_setstate(struct cpufreq_policy *policy,
                unsigned int table_index)
 {
        unsigned int mults_index;
@@ -258,10 +258,12 @@ static void longhaul_setstate(struct cpufreq_policy *policy,
        /* Safety precautions */
        mult = mults[mults_index & 0x1f];
        if (mult == -1)
-               return;
+               return -EINVAL;
+
        speed = calc_speed(mult);
        if ((speed > highest_speed) || (speed < lowest_speed))
-               return;
+               return -EINVAL;
+
        /* Voltage transition before frequency transition? */
        if (can_scale_voltage && longhaul_index < table_index)
                dir = 1;
@@ -269,8 +271,6 @@ static void longhaul_setstate(struct cpufreq_policy *policy,
        freqs.old = calc_speed(longhaul_get_cpu_mult());
        freqs.new = speed;
 
-       cpufreq_freq_transition_begin(policy, &freqs);
-
        pr_debug("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
                        fsb, mult/10, mult%10, print_speed(speed/1000));
 retry_loop:
@@ -385,12 +385,14 @@ retry_loop:
                        goto retry_loop;
                }
        }
-       /* Report true CPU frequency */
-       cpufreq_freq_transition_end(policy, &freqs, 0);
 
-       if (!bm_timeout)
+       if (!bm_timeout) {
                printk(KERN_INFO PFX "Warning: Timeout while waiting for "
                                "idle PCI bus.\n");
+               return -EBUSY;
+       }
+
+       return 0;
 }
 
 /*
@@ -631,9 +633,10 @@ static int longhaul_target(struct cpufreq_policy *policy,
        unsigned int i;
        unsigned int dir = 0;
        u8 vid, current_vid;
+       int retval = 0;
 
        if (!can_scale_voltage)
-               longhaul_setstate(policy, table_index);
+               retval = longhaul_setstate(policy, table_index);
        else {
                /* On test system voltage transitions exceeding single
                 * step up or down were turning motherboard off. Both
@@ -648,7 +651,7 @@ static int longhaul_target(struct cpufreq_policy *policy,
                while (i != table_index) {
                        vid = (longhaul_table[i].driver_data >> 8) & 0x1f;
                        if (vid != current_vid) {
-                               longhaul_setstate(policy, i);
+                               retval = longhaul_setstate(policy, i);
                                current_vid = vid;
                                msleep(200);
                        }
@@ -657,10 +660,11 @@ static int longhaul_target(struct cpufreq_policy *policy,
                        else
                                i--;
                }
-               longhaul_setstate(policy, table_index);
+               retval = longhaul_setstate(policy, table_index);
        }
+
        longhaul_index = table_index;
-       return 0;
+       return retval;
 }
 
 
@@ -968,7 +972,15 @@ static void __exit longhaul_exit(void)
 
        for (i = 0; i < numscales; i++) {
                if (mults[i] == maxmult) {
+                       struct cpufreq_freqs freqs;
+
+                       freqs.old = policy->cur;
+                       freqs.new = longhaul_table[i].frequency;
+                       freqs.flags = 0;
+
+                       cpufreq_freq_transition_begin(policy, &freqs);
                        longhaul_setstate(policy, i);
+                       cpufreq_freq_transition_end(policy, &freqs, 0);
                        break;
                }
        }
index f0bc31f..d4add86 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 49f120e..78904e6 100644 (file)
@@ -138,22 +138,14 @@ static void powernow_k6_set_cpu_multiplier(unsigned int best_i)
 static int powernow_k6_target(struct cpufreq_policy *policy,
                unsigned int best_i)
 {
-       struct cpufreq_freqs freqs;
 
        if (clock_ratio[best_i].driver_data > max_multiplier) {
                printk(KERN_ERR PFX "invalid target frequency\n");
                return -EINVAL;
        }
 
-       freqs.old = busfreq * powernow_k6_get_cpu_multiplier();
-       freqs.new = busfreq * clock_ratio[best_i].driver_data;
-
-       cpufreq_freq_transition_begin(policy, &freqs);
-
        powernow_k6_set_cpu_multiplier(best_i);
 
-       cpufreq_freq_transition_end(policy, &freqs, 0);
-
        return 0;
 }
 
@@ -227,9 +219,20 @@ have_busfreq:
 static int powernow_k6_cpu_exit(struct cpufreq_policy *policy)
 {
        unsigned int i;
-       for (i = 0; i < 8; i++) {
-               if (i == max_multiplier)
+
+       for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
+               if (clock_ratio[i].driver_data == max_multiplier) {
+                       struct cpufreq_freqs freqs;
+
+                       freqs.old = policy->cur;
+                       freqs.new = clock_ratio[i].frequency;
+                       freqs.flags = 0;
+
+                       cpufreq_freq_transition_begin(policy, &freqs);
                        powernow_k6_target(policy, i);
+                       cpufreq_freq_transition_end(policy, &freqs, 0);
+                       break;
+               }
        }
        return 0;
 }
index f911645..e61e224 100644 (file)
@@ -269,8 +269,6 @@ static int powernow_target(struct cpufreq_policy *policy, unsigned int index)
 
        freqs.new = powernow_table[index].frequency;
 
-       cpufreq_freq_transition_begin(policy, &freqs);
-
        /* Now do the magic poking into the MSRs.  */
 
        if (have_a0 == 1)       /* A0 errata 5 */
@@ -290,8 +288,6 @@ static int powernow_target(struct cpufreq_policy *policy, unsigned int index)
        if (have_a0 == 1)
                local_irq_enable();
 
-       cpufreq_freq_transition_end(policy, &freqs, 0);
-
        return 0;
 }
 
index a1ca3dd..0af618a 100644 (file)
@@ -138,6 +138,7 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy)
        struct cpufreq_frequency_table *table;
        struct cpu_data *data;
        unsigned int cpu = policy->cpu;
+       u64 transition_latency_hz;
 
        np = of_get_cpu_node(cpu, NULL);
        if (!np)
@@ -205,8 +206,10 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy)
        for_each_cpu(i, per_cpu(cpu_mask, cpu))
                per_cpu(cpu_data, i) = data;
 
+       transition_latency_hz = 12ULL * NSEC_PER_SEC;
        policy->cpuinfo.transition_latency =
-                               (12ULL * NSEC_PER_SEC) / fsl_get_sys_freq();
+               do_div(transition_latency_hz, fsl_get_sys_freq());
+
        of_node_put(np);
 
        return 0;
index 9f25f52..0eabd81 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 a886713..d5d30ed 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 cfdbb92..7a74076 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 766b68e..394cbc5 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 ab26d46..5ebdfbc 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 c98764a..f477308 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 8db6632..586f2f7 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 3ee852c..071c2c9 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 e73c675..7030422 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 99a6831..3d53fd6 100644 (file)
@@ -894,9 +894,11 @@ static int mcp23s08_probe(struct spi_device *spi)
                        dev_err(&spi->dev, "invalid spi-present-mask\n");
                        return -ENODEV;
                }
-
-               for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++)
+               for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
+                       if ((spi_present_mask & (1 << addr)))
+                               chips++;
                        pullups[addr] = 0;
+               }
        } else {
                type = spi_get_device_id(spi)->driver_data;
                pdata = dev_get_platdata(&spi->dev);
@@ -919,12 +921,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)
index df281b5..872ba11 100644 (file)
@@ -29,6 +29,7 @@
  *      Jesse Barnes <jesse.barnes@intel.com>
  */
 
+#include <linux/kernel.h>
 #include <linux/export.h>
 #include <linux/moduleparam.h>
 
@@ -88,7 +89,13 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
        struct drm_connector *connector;
        struct drm_device *dev = encoder->dev;
 
-       WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
+       /*
+        * We can expect this mutex to be locked if we are not panicking.
+        * Locking is currently fubar in the panic handler.
+        */
+       if (!oops_in_progress)
+               WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
+
        list_for_each_entry(connector, &dev->mode_config.connector_list, head)
                if (connector->encoder == encoder)
                        return true;
@@ -112,7 +119,13 @@ bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
        struct drm_encoder *encoder;
        struct drm_device *dev = crtc->dev;
 
-       WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
+       /*
+        * We can expect this mutex to be locked if we are not panicking.
+        * Locking is currently fubar in the panic handler.
+        */
+       if (!oops_in_progress)
+               WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
+
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
                if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder))
                        return true;
index e930d4f..1ef5ab9 100644 (file)
@@ -145,6 +145,7 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
 
        plane->crtc = crtc;
        plane->fb = crtc->primary->fb;
+       drm_framebuffer_reference(plane->fb);
 
        return 0;
 }
index c786cd4..2a3ad24 100644 (file)
@@ -263,7 +263,7 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
        buffer->sgt = sgt;
        exynos_gem_obj->base.import_attach = attach;
 
-       DRM_DEBUG_PRIME("dma_addr = 0x%x, size = 0x%lx\n", buffer->dma_addr,
+       DRM_DEBUG_PRIME("dma_addr = %pad, size = 0x%lx\n", &buffer->dma_addr,
                                                                buffer->size);
 
        return &exynos_gem_obj->base;
index eb73e3b..4ac4381 100644 (file)
@@ -1426,9 +1426,9 @@ static int exynos_dsi_probe(struct platform_device *pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        dsi->reg_base = devm_ioremap_resource(&pdev->dev, res);
-       if (!dsi->reg_base) {
+       if (IS_ERR(dsi->reg_base)) {
                dev_err(&pdev->dev, "failed to remap io region\n");
-               return -EADDRNOTAVAIL;
+               return PTR_ERR(dsi->reg_base);
        }
 
        dsi->phy = devm_phy_get(&pdev->dev, "dsim");
index 7afead9..852f2da 100644 (file)
@@ -220,7 +220,7 @@ static void vidi_win_commit(struct exynos_drm_manager *mgr, int zpos)
 
        win_data->enabled = true;
 
-       DRM_DEBUG_KMS("dma_addr = 0x%x\n", win_data->dma_addr);
+       DRM_DEBUG_KMS("dma_addr = %pad\n", &win_data->dma_addr);
 
        if (ctx->vblank_on)
                schedule_work(&ctx->work);
index 96177ee..eedb023 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 ec82f6b..388c028 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 2871ce7..3326770 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 75fca63..bbf4b12 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 2c9d9cb..20fef6c 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 ab5e93c..5deb228 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 false; /* HAS_PPGTT(dev) */
-       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 7753249..f98ba4e 100644 (file)
@@ -1362,10 +1362,20 @@ static inline void intel_hpd_irq_handler(struct drm_device *dev,
        spin_lock(&dev_priv->irq_lock);
        for (i = 1; i < HPD_NUM_PINS; i++) {
 
-               WARN_ONCE(hpd[i] & hotplug_trigger &&
-                         dev_priv->hpd_stats[i].hpd_mark == HPD_DISABLED,
-                         "Received HPD interrupt (0x%08x) on pin %d (0x%08x) although disabled\n",
-                         hotplug_trigger, i, hpd[i]);
+               if (hpd[i] & hotplug_trigger &&
+                   dev_priv->hpd_stats[i].hpd_mark == HPD_DISABLED) {
+                       /*
+                        * On GMCH platforms the interrupt mask bits only
+                        * prevent irq generation, not the setting of the
+                        * hotplug bits itself. So only WARN about unexpected
+                        * interrupts on saner platforms.
+                        */
+                       WARN_ONCE(INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev),
+                                 "Received HPD interrupt (0x%08x) on pin %d (0x%08x) although disabled\n",
+                                 hotplug_trigger, i, hpd[i]);
+
+                       continue;
+               }
 
                if (!(hpd[i] & hotplug_trigger) ||
                    dev_priv->hpd_stats[i].hpd_mark != HPD_ENABLED)
index 9f5b18d..c77af69 100644 (file)
@@ -827,6 +827,7 @@ enum punit_power_well {
 # define MI_FLUSH_ENABLE                               (1 << 12)
 # define ASYNC_FLIP_PERF_DISABLE                       (1 << 14)
 # define MODE_IDLE                                     (1 << 9)
+# define STOP_RING                                     (1 << 8)
 
 #define GEN6_GT_MODE   0x20d0
 #define GEN7_GT_MODE   0x7008
index fa486c5..aff4a11 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 dae976f..5b60e25 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);
        }
@@ -9654,11 +9649,22 @@ intel_pipe_config_compare(struct drm_device *dev,
        PIPE_CONF_CHECK_I(pipe_src_w);
        PIPE_CONF_CHECK_I(pipe_src_h);
 
-       PIPE_CONF_CHECK_I(gmch_pfit.control);
-       /* pfit ratios are autocomputed by the hw on gen4+ */
-       if (INTEL_INFO(dev)->gen < 4)
-               PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios);
-       PIPE_CONF_CHECK_I(gmch_pfit.lvds_border_bits);
+       /*
+        * FIXME: BIOS likes to set up a cloned config with lvds+external
+        * screen. Since we don't yet re-compute the pipe config when moving
+        * just the lvds port away to another pipe the sw tracking won't match.
+        *
+        * Proper atomic modesets with recomputed global state will fix this.
+        * Until then just don't check gmch state for inherited modes.
+        */
+       if (!PIPE_CONF_QUIRK(PIPE_CONFIG_QUIRK_INHERITED_MODE)) {
+               PIPE_CONF_CHECK_I(gmch_pfit.control);
+               /* pfit ratios are autocomputed by the hw on gen4+ */
+               if (INTEL_INFO(dev)->gen < 4)
+                       PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios);
+               PIPE_CONF_CHECK_I(gmch_pfit.lvds_border_bits);
+       }
+
        PIPE_CONF_CHECK_I(pch_pfit.enabled);
        if (current_config->pch_pfit.enabled) {
                PIPE_CONF_CHECK_I(pch_pfit.pos);
@@ -11384,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;
@@ -11474,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;
@@ -11557,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
@@ -11567,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
@@ -11616,6 +11624,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                            base.head) {
                memset(&crtc->config, 0, sizeof(crtc->config));
 
+               crtc->config.quirks |= PIPE_CONFIG_QUIRK_INHERITED_MODE;
+
                crtc->active = dev_priv->display.get_pipe_config(crtc,
                                                                 &crtc->config);
 
index d2a5588..2a00cb8 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);
@@ -3619,7 +3657,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 {
        struct drm_connector *connector = &intel_connector->base;
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-       struct drm_device *dev = intel_dig_port->base.base.dev;
+       struct intel_encoder *intel_encoder = &intel_dig_port->base;
+       struct drm_device *dev = intel_encoder->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_display_mode *fixed_mode = NULL;
        bool has_dpcd;
@@ -3629,6 +3668,14 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
        if (!is_edp(intel_dp))
                return true;
 
+       /* The VDD bit needs a power domain reference, so if the bit is already
+        * enabled when we boot, grab this reference. */
+       if (edp_have_panel_vdd(intel_dp)) {
+               enum intel_display_power_domain power_domain;
+               power_domain = intel_display_port_power_domain(intel_encoder);
+               intel_display_power_get(dev_priv, power_domain);
+       }
+
        /* Cache DPCD and EDID for edp. */
        intel_edp_panel_vdd_on(intel_dp);
        has_dpcd = intel_dp_get_dpcd(intel_dp);
index 0542de9..328b1a7 100644 (file)
@@ -236,7 +236,8 @@ struct intel_crtc_config {
         * tracked with quirk flags so that fastboot and state checker can act
         * accordingly.
         */
-#define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS (1<<0) /* unreliable sync mode.flags */
+#define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS      (1<<0) /* unreliable sync mode.flags */
+#define PIPE_CONFIG_QUIRK_INHERITED_MODE       (1<<1) /* mode inherited from firmware */
        unsigned long quirks;
 
        /* User requested mode, only valid as a starting point to
index b4d44e6..f73ba5e 100644 (file)
@@ -132,6 +132,16 @@ static int intelfb_create(struct drm_fb_helper *helper,
 
        mutex_lock(&dev->struct_mutex);
 
+       if (intel_fb &&
+           (sizes->fb_width > intel_fb->base.width ||
+            sizes->fb_height > intel_fb->base.height)) {
+               DRM_DEBUG_KMS("BIOS fb too small (%dx%d), we require (%dx%d),"
+                             " releasing it\n",
+                             intel_fb->base.width, intel_fb->base.height,
+                             sizes->fb_width, sizes->fb_height);
+               drm_framebuffer_unreference(&intel_fb->base);
+               intel_fb = ifbdev->fb = NULL;
+       }
        if (!intel_fb || WARN_ON(!intel_fb->obj)) {
                DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n");
                ret = intelfb_alloc(helper, sizes);
@@ -377,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 b0413e1..157267a 100644 (file)
@@ -821,11 +821,11 @@ static void intel_disable_hdmi(struct intel_encoder *encoder)
        }
 }
 
-static int hdmi_portclock_limit(struct intel_hdmi *hdmi)
+static int hdmi_portclock_limit(struct intel_hdmi *hdmi, bool respect_dvi_limit)
 {
        struct drm_device *dev = intel_hdmi_to_dev(hdmi);
 
-       if (!hdmi->has_hdmi_sink || IS_G4X(dev))
+       if ((respect_dvi_limit && !hdmi->has_hdmi_sink) || IS_G4X(dev))
                return 165000;
        else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8)
                return 300000;
@@ -837,7 +837,8 @@ static enum drm_mode_status
 intel_hdmi_mode_valid(struct drm_connector *connector,
                      struct drm_display_mode *mode)
 {
-       if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector)))
+       if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector),
+                                              true))
                return MODE_CLOCK_HIGH;
        if (mode->clock < 20000)
                return MODE_CLOCK_LOW;
@@ -879,7 +880,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
        struct drm_device *dev = encoder->base.dev;
        struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
        int clock_12bpc = pipe_config->adjusted_mode.crtc_clock * 3 / 2;
-       int portclock_limit = hdmi_portclock_limit(intel_hdmi);
+       int portclock_limit = hdmi_portclock_limit(intel_hdmi, false);
        int desired_bpp;
 
        if (intel_hdmi->color_range_auto) {
index d8adc91..129db0c 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 0eead16..cb8cfb7 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 19e94c3..d93dcf6 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 6bc68bd..79fb4cc 100644 (file)
@@ -437,32 +437,41 @@ static void ring_setup_phys_status_page(struct intel_ring_buffer *ring)
        I915_WRITE(HWS_PGA, addr);
 }
 
-static int init_ring_common(struct intel_ring_buffer *ring)
+static bool stop_ring(struct intel_ring_buffer *ring)
 {
-       struct drm_device *dev = ring->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_i915_gem_object *obj = ring->obj;
-       int ret = 0;
-       u32 head;
+       struct drm_i915_private *dev_priv = to_i915(ring->dev);
 
-       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
+       if (!IS_GEN2(ring->dev)) {
+               I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING));
+               if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) {
+                       DRM_ERROR("%s :timed out trying to stop ring\n", ring->name);
+                       return false;
+               }
+       }
 
-       /* Stop the ring if it's running. */
        I915_WRITE_CTL(ring, 0);
        I915_WRITE_HEAD(ring, 0);
        ring->write_tail(ring, 0);
-       if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000))
-               DRM_ERROR("%s :timed out trying to stop ring\n", ring->name);
 
-       if (I915_NEED_GFX_HWS(dev))
-               intel_ring_setup_status_page(ring);
-       else
-               ring_setup_phys_status_page(ring);
+       if (!IS_GEN2(ring->dev)) {
+               (void)I915_READ_CTL(ring);
+               I915_WRITE_MODE(ring, _MASKED_BIT_DISABLE(STOP_RING));
+       }
 
-       head = I915_READ_HEAD(ring) & HEAD_ADDR;
+       return (I915_READ_HEAD(ring) & HEAD_ADDR) == 0;
+}
 
-       /* G45 ring initialization fails to reset head to zero */
-       if (head != 0) {
+static int init_ring_common(struct intel_ring_buffer *ring)
+{
+       struct drm_device *dev = ring->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_gem_object *obj = ring->obj;
+       int ret = 0;
+
+       gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
+
+       if (!stop_ring(ring)) {
+               /* G45 ring initialization often fails to reset head to zero */
                DRM_DEBUG_KMS("%s head not reset to zero "
                              "ctl %08x head %08x tail %08x start %08x\n",
                              ring->name,
@@ -471,9 +480,7 @@ static int init_ring_common(struct intel_ring_buffer *ring)
                              I915_READ_TAIL(ring),
                              I915_READ_START(ring));
 
-               I915_WRITE_HEAD(ring, 0);
-
-               if (I915_READ_HEAD(ring) & HEAD_ADDR) {
+               if (!stop_ring(ring)) {
                        DRM_ERROR("failed to set %s head to zero "
                                  "ctl %08x head %08x tail %08x start %08x\n",
                                  ring->name,
@@ -481,9 +488,16 @@ static int init_ring_common(struct intel_ring_buffer *ring)
                                  I915_READ_HEAD(ring),
                                  I915_READ_TAIL(ring),
                                  I915_READ_START(ring));
+                       ret = -EIO;
+                       goto out;
                }
        }
 
+       if (I915_NEED_GFX_HWS(dev))
+               intel_ring_setup_status_page(ring);
+       else
+               ring_setup_phys_status_page(ring);
+
        /* Initialize the ring. This must happen _after_ we've cleared the ring
         * registers with the above sequence (the readback of the HEAD registers
         * also enforces ordering), otherwise the hw might lose the new ring
index 270a6a9..2b91c4b 100644 (file)
@@ -34,6 +34,7 @@ struct  intel_hw_status_page {
 #define I915_WRITE_IMR(ring, val) I915_WRITE(RING_IMR((ring)->mmio_base), val)
 
 #define I915_READ_MODE(ring) I915_READ(RING_MI_MODE((ring)->mmio_base))
+#define I915_WRITE_MODE(ring, val) I915_WRITE(RING_MI_MODE((ring)->mmio_base), val)
 
 enum intel_ring_hangcheck_action {
        HANGCHECK_IDLE = 0,
index d27155a..46be00d 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 f729dc7..d0c7577 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 3e6c0f3..ef9957d 100644 (file)
@@ -510,9 +510,8 @@ static void update_cursor(struct drm_crtc *crtc)
                                        MDP4_DMA_CURSOR_BLEND_CONFIG_CURSOR_EN);
                } else {
                        /* disable cursor: */
-                       mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_BASE(dma), 0);
-                       mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_BLEND_CONFIG(dma),
-                                       MDP4_DMA_CURSOR_BLEND_CONFIG_FORMAT(CURSOR_ARGB));
+                       mdp4_write(mdp4_kms, REG_MDP4_DMA_CURSOR_BASE(dma),
+                                       mdp4_kms->blank_cursor_iova);
                }
 
                /* and drop the iova ref + obj rev when done scanning out: */
@@ -574,11 +573,9 @@ static int mdp4_crtc_cursor_set(struct drm_crtc *crtc,
 
        if (old_bo) {
                /* drop our previous reference: */
-               msm_gem_put_iova(old_bo, mdp4_kms->id);
-               drm_gem_object_unreference_unlocked(old_bo);
+               drm_flip_work_queue(&mdp4_crtc->unref_cursor_work, old_bo);
        }
 
-       crtc_flush(crtc);
        request_pending(crtc, PENDING_CURSOR);
 
        return 0;
index c740ccd..8edd531 100644 (file)
@@ -70,12 +70,12 @@ irqreturn_t mdp4_irq(struct msm_kms *kms)
 
        VERB("status=%08x", status);
 
+       mdp_dispatch_irqs(mdp_kms, status);
+
        for (id = 0; id < priv->num_crtcs; id++)
                if (status & mdp4_crtc_vblank(priv->crtcs[id]))
                        drm_handle_vblank(dev, id);
 
-       mdp_dispatch_irqs(mdp_kms, status);
-
        return IRQ_HANDLED;
 }
 
index 272e707..0bb4faa 100644 (file)
@@ -144,6 +144,10 @@ static void mdp4_preclose(struct msm_kms *kms, struct drm_file *file)
 static void mdp4_destroy(struct msm_kms *kms)
 {
        struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
+       if (mdp4_kms->blank_cursor_iova)
+               msm_gem_put_iova(mdp4_kms->blank_cursor_bo, mdp4_kms->id);
+       if (mdp4_kms->blank_cursor_bo)
+               drm_gem_object_unreference(mdp4_kms->blank_cursor_bo);
        kfree(mdp4_kms);
 }
 
@@ -372,6 +376,23 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
                goto fail;
        }
 
+       mutex_lock(&dev->struct_mutex);
+       mdp4_kms->blank_cursor_bo = msm_gem_new(dev, SZ_16K, MSM_BO_WC);
+       mutex_unlock(&dev->struct_mutex);
+       if (IS_ERR(mdp4_kms->blank_cursor_bo)) {
+               ret = PTR_ERR(mdp4_kms->blank_cursor_bo);
+               dev_err(dev->dev, "could not allocate blank-cursor bo: %d\n", ret);
+               mdp4_kms->blank_cursor_bo = NULL;
+               goto fail;
+       }
+
+       ret = msm_gem_get_iova(mdp4_kms->blank_cursor_bo, mdp4_kms->id,
+                       &mdp4_kms->blank_cursor_iova);
+       if (ret) {
+               dev_err(dev->dev, "could not pin blank-cursor bo: %d\n", ret);
+               goto fail;
+       }
+
        return kms;
 
 fail:
index 66a4d31..715520c 100644 (file)
@@ -44,6 +44,10 @@ struct mdp4_kms {
        struct clk *lut_clk;
 
        struct mdp_irq error_handler;
+
+       /* empty/blank cursor bo to use when cursor is "disabled" */
+       struct drm_gem_object *blank_cursor_bo;
+       uint32_t blank_cursor_iova;
 };
 #define to_mdp4_kms(x) container_of(x, struct mdp4_kms, base)
 
index 353d494..f2b985b 100644 (file)
@@ -71,11 +71,11 @@ static void mdp5_irq_mdp(struct mdp_kms *mdp_kms)
 
        VERB("status=%08x", status);
 
+       mdp_dispatch_irqs(mdp_kms, status);
+
        for (id = 0; id < priv->num_crtcs; id++)
                if (status & mdp5_crtc_vblank(priv->crtcs[id]))
                        drm_handle_vblank(dev, id);
-
-       mdp_dispatch_irqs(mdp_kms, status);
 }
 
 irqreturn_t mdp5_irq(struct msm_kms *kms)
index 6c6d7d4..a752ab8 100644 (file)
@@ -62,11 +62,8 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
        dma_addr_t paddr;
        int ret, size;
 
-       /* only doing ARGB32 since this is what is needed to alpha-blend
-        * with video overlays:
-        */
        sizes->surface_bpp = 32;
-       sizes->surface_depth = 32;
+       sizes->surface_depth = 24;
 
        DBG("create fbdev: %dx%d@%d (%dx%d)", sizes->surface_width,
                        sizes->surface_height, sizes->surface_bpp,
index 3da8264..bb8026d 100644 (file)
@@ -118,8 +118,10 @@ static void put_pages(struct drm_gem_object *obj)
 
                if (iommu_present(&platform_bus_type))
                        drm_gem_put_pages(obj, msm_obj->pages, true, false);
-               else
+               else {
                        drm_mm_remove_node(msm_obj->vram_node);
+                       drm_free_large(msm_obj->pages);
+               }
 
                msm_obj->pages = NULL;
        }
index 7762665..876de9a 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 1dc37b1..b0d0fb2 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 fb0b6b2..222e8eb 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 43fec17..bbf117b 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 83face3..2792069 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 3ff030d..da764a4 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 fb187c7..e911898 100644 (file)
@@ -270,8 +270,6 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
        switch (mode) {
        case DRM_MODE_DPMS_ON:
                radeon_crtc->enabled = true;
-               /* adjust pm to dpms changes BEFORE enabling crtcs */
-               radeon_pm_compute_clocks(rdev);
                atombios_enable_crtc(crtc, ATOM_ENABLE);
                if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev))
                        atombios_enable_crtc_memreq(crtc, ATOM_ENABLE);
@@ -289,10 +287,10 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
                        atombios_enable_crtc_memreq(crtc, ATOM_DISABLE);
                atombios_enable_crtc(crtc, ATOM_DISABLE);
                radeon_crtc->enabled = false;
-               /* adjust pm to dpms changes AFTER disabling crtcs */
-               radeon_pm_compute_clocks(rdev);
                break;
        }
+       /* adjust pm to dpms */
+       radeon_pm_compute_clocks(rdev);
 }
 
 static void
@@ -1177,27 +1175,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 +1734,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 +1900,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 bc0119f..54e4f52 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 199eb19..d2fd989 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 f7e46cf..72e464c 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 2138732..dd79263 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 b406546..0f7a51a 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 287fe96..478caef 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 16ec9d5..3f6e817 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 6e887d0..bbc189f 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 53fcb28..4969cef 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 b58e1af..8149e7c 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 b8a24a7..e5f0177 100644 (file)
@@ -2049,8 +2049,8 @@ static struct radeon_asic ci_asic = {
                .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX,
                .dma = &cik_copy_dma,
                .dma_ring_index = R600_RING_TYPE_DMA_INDEX,
-               .copy = &cik_copy_dma,
-               .copy_ring_index = R600_RING_TYPE_DMA_INDEX,
+               .copy = &cik_copy_cpdma,
+               .copy_ring_index = RADEON_RING_TYPE_GFX_INDEX,
        },
        .surface = {
                .set_reg = r600_set_surface_reg,
@@ -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 b3633d9..9ab3097 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 2b6e0eb..41ecf8a 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 511fe26..2cd144c 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,16 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
        }
 
        drm_kms_helper_poll_enable(dev);
+
+       /* set the power state here in case we are a PX system or headless */
+       if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled)
+               radeon_pm_compute_clocks(rdev);
+
+       if (fbcon) {
+               radeon_fbdev_set_suspend(rdev, 0);
+               console_unlock();
+       }
+
        return 0;
 }
 
index 8d99d5e..356b733 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 9da5da4..4b7b87f 100644 (file)
@@ -97,6 +97,7 @@ enum radeon_family {
        CHIP_KAVERI,
        CHIP_KABINI,
        CHIP_HAWAII,
+       CHIP_MULLINS,
        CHIP_LAST,
 };
 
index 0cc47f1..eaaedba 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 19bec0d..4faa4d6 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 6fac8ef..2bdae61 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
@@ -1068,7 +1104,6 @@ static void radeon_pm_resume_dpm(struct radeon_device *rdev)
        if (ret)
                goto dpm_resume_fail;
        rdev->pm.dpm_enabled = true;
-       radeon_pm_compute_clocks(rdev);
        return;
 
 dpm_resume_fail:
@@ -1300,6 +1335,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 +1649,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 58d1293..4e7c326 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 5748bda..1b65ae2 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 ced53dd..3971d96 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 2aae6ce..c11b71d 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 + 2,
+                            sizeof(struct radeon_cs_reloc), GFP_KERNEL);
        if (!list)
                return NULL;
 
@@ -585,7 +585,8 @@ int radeon_vm_update_page_directory(struct radeon_device *rdev,
 {
        static const uint32_t incr = RADEON_VM_PTE_COUNT * 8;
 
-       uint64_t pd_addr = radeon_bo_gpu_offset(vm->page_directory);
+       struct radeon_bo *pd = vm->page_directory;
+       uint64_t pd_addr = radeon_bo_gpu_offset(pd);
        uint64_t last_pde = ~0, last_pt = ~0;
        unsigned count = 0, pt_idx, ndw;
        struct radeon_ib ib;
@@ -595,7 +596,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)
@@ -642,6 +643,7 @@ int radeon_vm_update_page_directory(struct radeon_device *rdev,
                                        incr, R600_PTE_VALID);
 
        if (ib.length_dw != 0) {
+               radeon_semaphore_sync_to(ib.semaphore, pd->tbo.sync_obj);
                radeon_semaphore_sync_to(ib.semaphore, vm->last_id_use);
                r = radeon_ib_schedule(rdev, &ib, NULL);
                if (r) {
@@ -689,15 +691,18 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev,
        /* walk over the address space and update the page tables */
        for (addr = start; addr < end; ) {
                uint64_t pt_idx = addr >> RADEON_VM_BLOCK_SIZE;
+               struct radeon_bo *pt = vm->page_tables[pt_idx].bo;
                unsigned nptes;
                uint64_t pte;
 
+               radeon_semaphore_sync_to(ib->semaphore, pt->tbo.sync_obj);
+
                if ((addr & ~mask) == (end & ~mask))
                        nptes = end - addr;
                else
                        nptes = RADEON_VM_PTE_COUNT - (addr & mask);
 
-               pte = radeon_bo_gpu_offset(vm->page_tables[pt_idx].bo);
+               pte = radeon_bo_gpu_offset(pt);
                pte += (addr & mask) * 8;
 
                if ((last_pte + 8 * count) != pte) {
index aca8cbe..bbf2e07 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 ac708e0..22a63c9 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 cf0fdad..de0ca07 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 683532f..7321283 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 0a243f0..be42c81 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 36c717a..edb871d 100644 (file)
@@ -312,7 +312,7 @@ static void tegra_crtc_disable(struct drm_crtc *crtc)
        struct drm_device *drm = crtc->dev;
        struct drm_plane *plane;
 
-       list_for_each_entry(plane, &drm->mode_config.plane_list, head) {
+       drm_for_each_legacy_plane(plane, &drm->mode_config.plane_list) {
                if (plane->crtc == crtc) {
                        tegra_plane_disable(plane);
                        plane->crtc = NULL;
index 931490b..87df0b3 100644 (file)
@@ -1214,14 +1214,36 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
                SVGA3dCmdSurfaceDMA dma;
        } *cmd;
        int ret;
+       SVGA3dCmdSurfaceDMASuffix *suffix;
+       uint32_t bo_size;
 
        cmd = container_of(header, struct vmw_dma_cmd, header);
+       suffix = (SVGA3dCmdSurfaceDMASuffix *)((unsigned long) &cmd->dma +
+                                              header->size - sizeof(*suffix));
+
+       /* Make sure device and verifier stays in sync. */
+       if (unlikely(suffix->suffixSize != sizeof(*suffix))) {
+               DRM_ERROR("Invalid DMA suffix size.\n");
+               return -EINVAL;
+       }
+
        ret = vmw_translate_guest_ptr(dev_priv, sw_context,
                                      &cmd->dma.guest.ptr,
                                      &vmw_bo);
        if (unlikely(ret != 0))
                return ret;
 
+       /* Make sure DMA doesn't cross BO boundaries. */
+       bo_size = vmw_bo->base.num_pages * PAGE_SIZE;
+       if (unlikely(cmd->dma.guest.ptr.offset > bo_size)) {
+               DRM_ERROR("Invalid DMA offset.\n");
+               return -EINVAL;
+       }
+
+       bo_size -= cmd->dma.guest.ptr.offset;
+       if (unlikely(suffix->maximumOffset > bo_size))
+               suffix->maximumOffset = bo_size;
+
        ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
                                user_surface_converter, &cmd->dma.host.sid,
                                NULL);
index 10a2c08..da52279 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 c8af720..34bb220 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 35278e4..51e25b9 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 af8244b..be14b56 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 dbd8387..8e4ddb3 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 bc196f4..4af0da9 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 6d02e3b..d76f0b7 100644 (file)
@@ -365,12 +365,12 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
                if (cpu_has_tjmax(c))
                        dev_warn(dev, "Unable to read TjMax from CPU %u\n", id);
        } else {
-               val = (eax >> 16) & 0x7f;
+               val = (eax >> 16) & 0xff;
                /*
                 * If the TjMax is not plausible, an assumption
                 * will be used
                 */
-               if (val >= 85) {
+               if (val) {
                        dev_dbg(dev, "TjMax is %d degrees C\n", val);
                        return val * 1000;
                }
index 90ec117..01723f0 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 8a17f01..e76feb8 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 22e92c3..3c20e4b 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 28cbe1b..32c85e9 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 1b4cf14..2a5efb5 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 d4fa8eb..06d47aa 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 ae44910..bb3a996 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 d86196c..24c28e3 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 d25b262..affa93f 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 cb9f96b..d8ad606 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 d4e8983..23f38cf 100644 (file)
@@ -1,10 +1,10 @@
 config INFINIBAND_CXGB4
-       tristate "Chelsio T4 RDMA Driver"
+       tristate "Chelsio T4/T5 RDMA Driver"
        depends on CHELSIO_T4 && INET && (IPV6 || IPV6=n)
        select GENERIC_ALLOCATOR
        ---help---
-         This is an iWARP/RDMA driver for the Chelsio T4 1GbE and
-         10GbE adapters.
+         This is an iWARP/RDMA driver for the Chelsio T4 and T5
+         1GbE, 10GbE adapters and T5 40GbE adapter.
 
          For general information about Chelsio and our products, visit
          our website at <http://www.chelsio.com>.
index 185452a..1f863a9 100644 (file)
@@ -587,6 +587,10 @@ static int send_connect(struct c4iw_ep *ep)
                opt2 |= SACK_EN(1);
        if (wscale && enable_tcp_window_scaling)
                opt2 |= WND_SCALE_EN(1);
+       if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) {
+               opt2 |= T5_OPT_2_VALID;
+               opt2 |= V_CONG_CNTRL(CONG_ALG_TAHOE);
+       }
        t4_set_arp_err_handler(skb, NULL, act_open_req_arp_failure);
 
        if (is_t4(ep->com.dev->rdev.lldi.adapter_type)) {
@@ -996,7 +1000,7 @@ static void close_complete_upcall(struct c4iw_ep *ep, int status)
 static int abort_connection(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
 {
        PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
-       state_set(&ep->com, ABORTING);
+       __state_set(&ep->com, ABORTING);
        set_bit(ABORT_CONN, &ep->com.history);
        return send_abort(ep, skb, gfp);
 }
@@ -1154,7 +1158,7 @@ static int update_rx_credits(struct c4iw_ep *ep, u32 credits)
        return credits;
 }
 
-static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
+static int process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
 {
        struct mpa_message *mpa;
        struct mpa_v2_conn_params *mpa_v2_params;
@@ -1164,6 +1168,7 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
        struct c4iw_qp_attributes attrs;
        enum c4iw_qp_attr_mask mask;
        int err;
+       int disconnect = 0;
 
        PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 
@@ -1173,7 +1178,7 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
         * will abort the connection.
         */
        if (stop_ep_timer(ep))
-               return;
+               return 0;
 
        /*
         * If we get more than the supported amount of private data
@@ -1195,7 +1200,7 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
         * if we don't even have the mpa message, then bail.
         */
        if (ep->mpa_pkt_len < sizeof(*mpa))
-               return;
+               return 0;
        mpa = (struct mpa_message *) ep->mpa_pkt;
 
        /* Validate MPA header. */
@@ -1235,7 +1240,7 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
         * We'll continue process when more data arrives.
         */
        if (ep->mpa_pkt_len < (sizeof(*mpa) + plen))
-               return;
+               return 0;
 
        if (mpa->flags & MPA_REJECT) {
                err = -ECONNREFUSED;
@@ -1337,9 +1342,11 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
                attrs.layer_etype = LAYER_MPA | DDP_LLP;
                attrs.ecode = MPA_NOMATCH_RTR;
                attrs.next_state = C4IW_QP_STATE_TERMINATE;
+               attrs.send_term = 1;
                err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
-                               C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+                               C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
                err = -ENOMEM;
+               disconnect = 1;
                goto out;
        }
 
@@ -1355,9 +1362,11 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
                attrs.layer_etype = LAYER_MPA | DDP_LLP;
                attrs.ecode = MPA_INSUFF_IRD;
                attrs.next_state = C4IW_QP_STATE_TERMINATE;
+               attrs.send_term = 1;
                err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
-                               C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+                               C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
                err = -ENOMEM;
+               disconnect = 1;
                goto out;
        }
        goto out;
@@ -1366,7 +1375,7 @@ err:
        send_abort(ep, skb, GFP_KERNEL);
 out:
        connect_reply_upcall(ep, err);
-       return;
+       return disconnect;
 }
 
 static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
@@ -1524,6 +1533,7 @@ static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb)
        unsigned int tid = GET_TID(hdr);
        struct tid_info *t = dev->rdev.lldi.tids;
        __u8 status = hdr->status;
+       int disconnect = 0;
 
        ep = lookup_tid(t, tid);
        if (!ep)
@@ -1539,7 +1549,7 @@ static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb)
        switch (ep->com.state) {
        case MPA_REQ_SENT:
                ep->rcv_seq += dlen;
-               process_mpa_reply(ep, skb);
+               disconnect = process_mpa_reply(ep, skb);
                break;
        case MPA_REQ_WAIT:
                ep->rcv_seq += dlen;
@@ -1555,13 +1565,16 @@ static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb)
                               ep->com.state, ep->hwtid, status);
                attrs.next_state = C4IW_QP_STATE_TERMINATE;
                c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
-                              C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
+                              C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
+               disconnect = 1;
                break;
        }
        default:
                break;
        }
        mutex_unlock(&ep->com.mutex);
+       if (disconnect)
+               c4iw_ep_disconnect(ep, 0, GFP_KERNEL);
        return 0;
 }
 
@@ -2009,6 +2022,10 @@ static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,
                if (tcph->ece && tcph->cwr)
                        opt2 |= CCTRL_ECN(1);
        }
+       if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) {
+               opt2 |= T5_OPT_2_VALID;
+               opt2 |= V_CONG_CNTRL(CONG_ALG_TAHOE);
+       }
 
        rpl = cplhdr(skb);
        INIT_TP_WR(rpl, ep->hwtid);
@@ -3482,9 +3499,9 @@ static void process_timeout(struct c4iw_ep *ep)
                        __func__, ep, ep->hwtid, ep->com.state);
                abort = 0;
        }
-       mutex_unlock(&ep->com.mutex);
        if (abort)
                abort_connection(ep, NULL, GFP_KERNEL);
+       mutex_unlock(&ep->com.mutex);
        c4iw_put_ep(&ep->com);
 }
 
index 7b8c580..7474b49 100644 (file)
@@ -435,6 +435,7 @@ struct c4iw_qp_attributes {
        u8 ecode;
        u16 sq_db_inc;
        u16 rq_db_inc;
+       u8 send_term;
 };
 
 struct c4iw_qp {
index 7b5114c..086f62f 100644 (file)
@@ -1388,11 +1388,12 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
                        qhp->attr.layer_etype = attrs->layer_etype;
                        qhp->attr.ecode = attrs->ecode;
                        ep = qhp->ep;
-                       disconnect = 1;
-                       c4iw_get_ep(&qhp->ep->com);
-                       if (!internal)
+                       if (!internal) {
+                               c4iw_get_ep(&qhp->ep->com);
                                terminate = 1;
-                       else {
+                               disconnect = 1;
+                       } else {
+                               terminate = qhp->attr.send_term;
                                ret = rdma_fini(rhp, qhp, ep);
                                if (ret)
                                        goto err;
@@ -1776,11 +1777,15 @@ int c4iw_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
        /*
         * Use SQ_PSN and RQ_PSN to pass in IDX_INC values for
         * ringing the queue db when we're in DB_FULL mode.
+        * Only allow this on T4 devices.
         */
        attrs.sq_db_inc = attr->sq_psn;
        attrs.rq_db_inc = attr->rq_psn;
        mask |= (attr_mask & IB_QP_SQ_PSN) ? C4IW_QP_ATTR_SQ_DB : 0;
        mask |= (attr_mask & IB_QP_RQ_PSN) ? C4IW_QP_ATTR_RQ_DB : 0;
+       if (is_t5(to_c4iw_qp(ibqp)->rhp->rdev.lldi.adapter_type) &&
+           (mask & (C4IW_QP_ATTR_SQ_DB|C4IW_QP_ATTR_RQ_DB)))
+               return -EINVAL;
 
        return c4iw_modify_qp(rhp, qhp, mask, &attrs, 0);
 }
index dc193c2..6121ca0 100644 (file)
@@ -836,4 +836,18 @@ struct ulptx_idata {
 #define V_RX_DACK_CHANGE(x) ((x) << S_RX_DACK_CHANGE)
 #define F_RX_DACK_CHANGE    V_RX_DACK_CHANGE(1U)
 
+enum {                     /* TCP congestion control algorithms */
+       CONG_ALG_RENO,
+       CONG_ALG_TAHOE,
+       CONG_ALG_NEWRENO,
+       CONG_ALG_HIGHSPEED
+};
+
+#define S_CONG_CNTRL    14
+#define M_CONG_CNTRL    0x3
+#define V_CONG_CNTRL(x) ((x) << S_CONG_CNTRL)
+#define G_CONG_CNTRL(x) (((x) >> S_CONG_CNTRL) & M_CONG_CNTRL)
+
+#define T5_OPT_2_VALID       (1 << 31)
+
 #endif /* _T4FW_RI_API_H_ */
index 1b6dbe1..199c789 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 f589522..66b0b7d 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 41308af..dc57482 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 76842d7..ffc7ad3 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 2626773..2dd1d0d 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 d8241ba..a15063b 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 55c1530..4e491c1 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 52d3a9b..b36831c 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 effa9c5..6b8441f 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 088d354..b96e978 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 036a04a..9e0e2a1 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 ef9f491..c5ec703 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 762b084..8b748d9 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 68edc9d..b845e93 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 c949520..57068e8 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 b76c58d..0e08545 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 5208828..203b2e6 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 41be897..3899ba7 100644 (file)
@@ -41,6 +41,7 @@
 #define ARMADA_370_XP_INT_SET_ENABLE_OFFS      (0x30)
 #define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS    (0x34)
 #define ARMADA_370_XP_INT_SOURCE_CTL(irq)      (0x100 + irq*4)
+#define ARMADA_370_XP_INT_SOURCE_CPU_MASK      0xF
 
 #define ARMADA_370_XP_CPU_INTACK_OFFS          (0x44)
 #define ARMADA_375_PPI_CAUSE                   (0x10)
@@ -132,8 +133,7 @@ static int armada_370_xp_setup_msi_irq(struct msi_chip *chip,
                                       struct msi_desc *desc)
 {
        struct msi_msg msg;
-       irq_hw_number_t hwirq;
-       int virq;
+       int virq, hwirq;
 
        hwirq = armada_370_xp_alloc_msi();
        if (hwirq < 0)
@@ -159,8 +159,19 @@ static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip,
                                           unsigned int irq)
 {
        struct irq_data *d = irq_get_irq_data(irq);
+       unsigned long hwirq = d->hwirq;
+
        irq_dispose_mapping(irq);
-       armada_370_xp_free_msi(d->hwirq);
+       armada_370_xp_free_msi(hwirq);
+}
+
+static int armada_370_xp_check_msi_device(struct msi_chip *chip, struct pci_dev *dev,
+                                         int nvec, int type)
+{
+       /* We support MSI, but not MSI-X */
+       if (type == PCI_CAP_ID_MSI)
+               return 0;
+       return -EINVAL;
 }
 
 static struct irq_chip armada_370_xp_msi_irq_chip = {
@@ -201,6 +212,7 @@ static int armada_370_xp_msi_init(struct device_node *node,
 
        msi_chip->setup_irq = armada_370_xp_setup_msi_irq;
        msi_chip->teardown_irq = armada_370_xp_teardown_msi_irq;
+       msi_chip->check_device = armada_370_xp_check_msi_device;
        msi_chip->of_node = node;
 
        armada_370_xp_msi_domain =
@@ -244,35 +256,18 @@ static DEFINE_RAW_SPINLOCK(irq_controller_lock);
 static int armada_xp_set_affinity(struct irq_data *d,
                                  const struct cpumask *mask_val, bool force)
 {
-       unsigned long reg;
-       unsigned long new_mask = 0;
-       unsigned long online_mask = 0;
-       unsigned long count = 0;
        irq_hw_number_t hwirq = irqd_to_hwirq(d);
+       unsigned long reg, mask;
        int cpu;
 
-       for_each_cpu(cpu, mask_val) {
-               new_mask |= 1 << cpu_logical_map(cpu);
-               count++;
-       }
-
-       /*
-        * Forbid mutlicore interrupt affinity
-        * This is required since the MPIC HW doesn't limit
-        * several CPUs from acknowledging the same interrupt.
-        */
-       if (count > 1)
-               return -EINVAL;
-
-       for_each_cpu(cpu, cpu_online_mask)
-               online_mask |= 1 << cpu_logical_map(cpu);
+       /* Select a single core from the affinity mask which is online */
+       cpu = cpumask_any_and(mask_val, cpu_online_mask);
+       mask = 1UL << cpu_logical_map(cpu);
 
        raw_spin_lock(&irq_controller_lock);
-
        reg = readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));
-       reg = (reg & (~online_mask)) | new_mask;
+       reg = (reg & (~ARMADA_370_XP_INT_SOURCE_CPU_MASK)) | mask;
        writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));
-
        raw_spin_unlock(&irq_controller_lock);
 
        return 0;
@@ -494,15 +489,6 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
 
 #ifdef CONFIG_SMP
        armada_xp_mpic_smp_cpu_init();
-
-       /*
-        * Set the default affinity from all CPUs to the boot cpu.
-        * This is required since the MPIC doesn't limit several CPUs
-        * from acknowledging the same interrupt.
-        */
-       cpumask_clear(irq_default_affinity);
-       cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
-
 #endif
 
        armada_370_xp_msi_init(node, main_int_res.start);
index fc817d2..3d15d16 100644 (file)
@@ -107,7 +107,7 @@ static int __init crossbar_of_init(struct device_node *node)
        int i, size, max, reserved = 0, entry;
        const __be32 *irqsr;
 
-       cb = kzalloc(sizeof(struct cb_device *), GFP_KERNEL);
+       cb = kzalloc(sizeof(*cb), GFP_KERNEL);
 
        if (!cb)
                return -ENOMEM;
index 51dae91..96d1df0 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 1bf4a71..5f054c4 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);
@@ -2488,6 +2490,7 @@ static int cache_map(struct dm_target *ti, struct bio *bio)
 
                } else {
                        inc_hit_counter(cache, bio);
+                       pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
 
                        if (bio_data_dir(bio) == WRITE && writethrough_mode(&cache->features) &&
                            !is_dirty(cache, lookup_result.cblock))
index 784695d..53b2132 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 aa009e8..ebfa411 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 53728be..242ac2e 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;
@@ -232,6 +236,13 @@ struct thin_c {
        struct bio_list deferred_bio_list;
        struct bio_list retry_on_resume_list;
        struct rb_root sort_bio_list; /* sorted list of deferred bios */
+
+       /*
+        * Ensures the thin is not destroyed until the worker has finished
+        * iterating the active_thins list.
+        */
+       atomic_t refcount;
+       struct completion can_destroy;
 };
 
 /*----------------------------------------------------------------*/
@@ -928,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);
@@ -1486,6 +1497,45 @@ static void process_thin_deferred_bios(struct thin_c *tc)
        blk_finish_plug(&plug);
 }
 
+static void thin_get(struct thin_c *tc);
+static void thin_put(struct thin_c *tc);
+
+/*
+ * We can't hold rcu_read_lock() around code that can block.  So we
+ * find a thin with the rcu lock held; bump a refcount; then drop
+ * the lock.
+ */
+static struct thin_c *get_first_thin(struct pool *pool)
+{
+       struct thin_c *tc = NULL;
+
+       rcu_read_lock();
+       if (!list_empty(&pool->active_thins)) {
+               tc = list_entry_rcu(pool->active_thins.next, struct thin_c, list);
+               thin_get(tc);
+       }
+       rcu_read_unlock();
+
+       return tc;
+}
+
+static struct thin_c *get_next_thin(struct pool *pool, struct thin_c *tc)
+{
+       struct thin_c *old_tc = tc;
+
+       rcu_read_lock();
+       list_for_each_entry_continue_rcu(tc, &pool->active_thins, list) {
+               thin_get(tc);
+               thin_put(old_tc);
+               rcu_read_unlock();
+               return tc;
+       }
+       thin_put(old_tc);
+       rcu_read_unlock();
+
+       return NULL;
+}
+
 static void process_deferred_bios(struct pool *pool)
 {
        unsigned long flags;
@@ -1493,10 +1543,11 @@ static void process_deferred_bios(struct pool *pool)
        struct bio_list bios;
        struct thin_c *tc;
 
-       rcu_read_lock();
-       list_for_each_entry_rcu(tc, &pool->active_thins, list)
+       tc = get_first_thin(pool);
+       while (tc) {
                process_thin_deferred_bios(tc);
-       rcu_read_unlock();
+               tc = get_next_thin(pool, tc);
+       }
 
        /*
         * If there are any deferred flush bios, we must commit
@@ -1543,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 {
@@ -1578,7 +1643,7 @@ static void noflush_work(struct thin_c *tc, void (*fn)(struct work_struct *))
 {
        struct noflush_work w;
 
-       INIT_WORK(&w.worker, fn);
+       INIT_WORK_ONSTACK(&w.worker, fn);
        w.tc = tc;
        atomic_set(&w.complete, 0);
        init_waitqueue_head(&w.wait);
@@ -1607,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
@@ -1668,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:
@@ -2053,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);
@@ -2615,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);
 }
@@ -3061,11 +3132,25 @@ static struct target_type pool_target = {
 /*----------------------------------------------------------------
  * Thin target methods
  *--------------------------------------------------------------*/
+static void thin_get(struct thin_c *tc)
+{
+       atomic_inc(&tc->refcount);
+}
+
+static void thin_put(struct thin_c *tc)
+{
+       if (atomic_dec_and_test(&tc->refcount))
+               complete(&tc->can_destroy);
+}
+
 static void thin_dtr(struct dm_target *ti)
 {
        struct thin_c *tc = ti->private;
        unsigned long flags;
 
+       thin_put(tc);
+       wait_for_completion(&tc->can_destroy);
+
        spin_lock_irqsave(&tc->pool->lock, flags);
        list_del_rcu(&tc->list);
        spin_unlock_irqrestore(&tc->pool->lock, flags);
@@ -3101,6 +3186,7 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
        struct thin_c *tc;
        struct dm_dev *pool_dev, *origin_dev;
        struct mapped_device *pool_md;
+       unsigned long flags;
 
        mutex_lock(&dm_thin_pool_table.mutex);
 
@@ -3191,9 +3277,12 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
 
        mutex_unlock(&dm_thin_pool_table.mutex);
 
-       spin_lock(&tc->pool->lock);
+       atomic_set(&tc->refcount, 1);
+       init_completion(&tc->can_destroy);
+
+       spin_lock_irqsave(&tc->pool->lock, flags);
        list_add_tail_rcu(&tc->list, &tc->pool->active_thins);
-       spin_unlock(&tc->pool->lock);
+       spin_unlock_irqrestore(&tc->pool->lock, flags);
        /*
         * This synchronize_rcu() call is needed here otherwise we risk a
         * wake_worker() call finding no bios to process (because the newly
@@ -3422,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 796007a..7a7bab8 100644 (file)
@@ -330,15 +330,17 @@ test_block_hash:
                                return r;
                        }
                }
-
                todo = 1 << v->data_dev_block_bits;
-               while (io->iter.bi_size) {
+               do {
                        u8 *page;
+                       unsigned len;
                        struct bio_vec bv = bio_iter_iovec(bio, io->iter);
 
                        page = kmap_atomic(bv.bv_page);
-                       r = crypto_shash_update(desc, page + bv.bv_offset,
-                                               bv.bv_len);
+                       len = bv.bv_len;
+                       if (likely(len >= todo))
+                               len = todo;
+                       r = crypto_shash_update(desc, page + bv.bv_offset, len);
                        kunmap_atomic(page);
 
                        if (r < 0) {
@@ -346,8 +348,9 @@ test_block_hash:
                                return r;
                        }
 
-                       bio_advance_iter(bio, &io->iter, bv.bv_len);
-               }
+                       bio_advance_iter(bio, &io->iter, len);
+                       todo -= len;
+               } while (todo);
 
                if (!v->version) {
                        r = crypto_shash_update(desc, v->salt, v->salt_size);
index 8fda38d..2382cfc 100644 (file)
@@ -7381,8 +7381,10 @@ void md_do_sync(struct md_thread *thread)
        /* just incase thread restarts... */
        if (test_bit(MD_RECOVERY_DONE, &mddev->recovery))
                return;
-       if (mddev->ro) /* never try to sync a read-only array */
+       if (mddev->ro) {/* never try to sync a read-only array */
+               set_bit(MD_RECOVERY_INTR, &mddev->recovery);
                return;
+       }
 
        if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
                if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) {
@@ -7824,6 +7826,7 @@ void md_check_recovery(struct mddev *mddev)
                        /* There is no thread, but we need to call
                         * ->spare_active and clear saved_raid_disk
                         */
+                       set_bit(MD_RECOVERY_INTR, &mddev->recovery);
                        md_reap_sync_thread(mddev);
                        clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
                        goto unlock;
@@ -8516,7 +8519,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 33fc408..cb882aa 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 e8a1ce2..cdd7c1b 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 a445930..ee0f57e 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 d5a7a13..703560f 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 b4f12d0..6567082 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 d762246..0379cb9 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 756da78..8dea0b8 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 0ac841e..aed41ed 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 da2fc86..25dbf5b 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 3aecaf4..f0c9c42 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 be38a9e..646c994 100644 (file)
@@ -22,6 +22,7 @@
 #define FC2580_PRIV_H
 
 #include "fc2580.h"
+#include <linux/math64.h>
 
 struct fc2580_reg_val {
        u8 reg;
index 7407b83..bc38f03 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 61d196e..dcbd392 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 7277dbd..ecbcb39 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 04b2daf..7e2411c 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 110c036..b59a17f 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 c9de3d5..1d15735 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 5fb994f..0b9ded1 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 4615d79..b922c8e 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 7ff473c..8d659e6 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 02317c1..0f3425d 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 9f69e81..93580a4 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 69aff72..d3a6789 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 724e30f..8320702 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 0e8b268..5f6babc 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 b8bdd0a..00bea32 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 a5c8dcf..95e04e2 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 faa8404..c56f1b1 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 bce0be5..fe5f630 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 806d927..1df0b32 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 c7a2604..e318e87 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 a3d99a8..ab7f1b0 100644 (file)
@@ -97,6 +97,9 @@ static int can_led_notifier(struct notifier_block *nb, unsigned long msg,
        if (!priv)
                return NOTIFY_DONE;
 
+       if (!priv->tx_led_trig || !priv->rx_led_trig)
+               return NOTIFY_DONE;
+
        if (msg == NETDEV_CHANGENAME) {
                snprintf(name, sizeof(name), "%s-tx", netdev->name);
                led_trigger_rename_static(name, priv->tx_led_trig);
index c540e3d..564933a 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 df136a2..014695d 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 f5b16e0..dcf9196 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 39b26fe..0513494 100644 (file)
@@ -35,6 +35,19 @@ 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
+       depends on X86 || COMPILE_TEST
+       ---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 545d0b3..35190e3 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 80c1ab7..fdddba5 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 d4a187e..3eff2fd 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 3df1866..0fb986b 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 7f0f5bf..42cf61c 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 d7b59ba..e335626 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 0ee9663..99cc56f 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 07d4717..584977e 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 ba3334f..85bc33b 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 8feeed0..2adb24d 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 319ca74..54c25ef 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 c70a29e..7330681 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 70fa13f..d7eeb17 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 ce1db36..baf100c 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 928fac6..53f85bf 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 eeecc29..d647a7d 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 a78edac..3b0d431 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 5c523b3..b8078d5 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 8bf7645..6929adb 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 0622884..784c715 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 7e49c43..9e089d2 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 ca97005..e9daa07 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 d40c994..570222c 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 6fe5891..24e16e3 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 a186454..dc19bc5 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 9125d9a..e2d4247 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 891dbee..76d7070 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 9d75fef..63eb959 100644 (file)
@@ -682,10 +682,7 @@ static int mal_probe(struct platform_device *ofdev)
                goto fail6;
 
        /* Enable all MAL SERR interrupt sources */
-       if (mal->version == 2)
-               set_mal_dcrn(mal, MAL_IER, MAL2_IER_EVENTS);
-       else
-               set_mal_dcrn(mal, MAL_IER, MAL1_IER_EVENTS);
+       set_mal_dcrn(mal, MAL_IER, MAL_IER_EVENTS);
 
        /* Enable EOB interrupt */
        mal_enable_eob_irq(mal);
index e431a32..eeade2e 100644 (file)
 
 
 #define MAL_IER                        0x02
+/* MAL IER bits */
 #define   MAL_IER_DE           0x00000010
 #define   MAL_IER_OTE          0x00000004
 #define   MAL_IER_OE           0x00000002
 #define   MAL_IER_PE           0x00000001
-/* MAL V1 IER bits */
-#define   MAL1_IER_NWE         0x00000008
-#define   MAL1_IER_SOC_EVENTS  MAL1_IER_NWE
-#define   MAL1_IER_EVENTS      (MAL1_IER_SOC_EVENTS | MAL_IER_DE | \
-                                MAL_IER_OTE | MAL_IER_OE | MAL_IER_PE)
 
-/* MAL V2 IER bits */
-#define   MAL2_IER_PT          0x00000080
-#define   MAL2_IER_PRE         0x00000040
-#define   MAL2_IER_PWE         0x00000020
-#define   MAL2_IER_SOC_EVENTS  (MAL2_IER_PT | MAL2_IER_PRE | MAL2_IER_PWE)
-#define   MAL2_IER_EVENTS      (MAL2_IER_SOC_EVENTS | MAL_IER_DE | \
-                                MAL_IER_OTE | MAL_IER_OE | MAL_IER_PE)
+/* PLB read/write/timeout errors */
+#define   MAL_IER_PTE          0x00000080
+#define   MAL_IER_PRE          0x00000040
+#define   MAL_IER_PWE          0x00000020
 
+#define   MAL_IER_SOC_EVENTS   (MAL_IER_PTE | MAL_IER_PRE | MAL_IER_PWE)
+#define   MAL_IER_EVENTS       (MAL_IER_SOC_EVENTS | MAL_IER_DE | \
+                                MAL_IER_OTE | MAL_IER_OE | MAL_IER_PE)
 
 #define MAL_TXCASR             0x04
 #define MAL_TXCARR             0x05
index 4fb2f96..a01182c 100644 (file)
@@ -45,6 +45,7 @@
 
 /* RGMIIx_SSR */
 #define RGMII_SSR_MASK(idx)    (0x7 << ((idx) * 8))
+#define RGMII_SSR_10(idx)      (0x1 << ((idx) * 8))
 #define RGMII_SSR_100(idx)     (0x2 << ((idx) * 8))
 #define RGMII_SSR_1000(idx)    (0x4 << ((idx) * 8))
 
@@ -139,6 +140,8 @@ void rgmii_set_speed(struct platform_device *ofdev, int input, int speed)
                ssr |= RGMII_SSR_1000(input);
        else if (speed == SPEED_100)
                ssr |= RGMII_SSR_100(input);
+       else if (speed == SPEED_10)
+               ssr |= RGMII_SSR_10(input);
 
        out_be32(&p->ssr, ssr);
 
index 9866f26..f0bbd42 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 bead50f..5515126 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 d50c91e..3e69386 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 3841bcc..537d278 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 861b722..cf0761f 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 262bdf1..8129918 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 e33ec6c..e61e637 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 0f5d96a..9478ddc 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 db96339..f67f8a1 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 5910a93..1e0c404 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 fb98d46..16430a8 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 9209d65..ab25e49 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 1a12c1d..c6c4ca7 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 24fba39..981b8a7 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 c4c526b..d62e7a2 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 23f7652..a76af8e 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 63515a6..8902ae6 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 b0c6050..b78378c 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 b161a52..9d5ced2 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 78099ea..92d3249 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 cef267e..c187d74 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);
 }
 
 /*
@@ -2044,6 +2044,7 @@ static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
        if (!mlx4_is_slave(dev)) {
                mlx4_init_mac_table(dev, &info->mac_table);
                mlx4_init_vlan_table(dev, &info->vlan_table);
+               mlx4_init_roce_gid_table(dev, &info->gid_table);
                info->base_qpn = mlx4_get_base_qpn(dev, port);
        }
 
@@ -2440,7 +2441,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 f9c4651..8e9eb02 100644 (file)
@@ -695,6 +695,17 @@ struct mlx4_mac_table {
        int                     max;
 };
 
+#define MLX4_ROCE_GID_ENTRY_SIZE       16
+
+struct mlx4_roce_gid_entry {
+       u8 raw[MLX4_ROCE_GID_ENTRY_SIZE];
+};
+
+struct mlx4_roce_gid_table {
+       struct mlx4_roce_gid_entry      roce_gids[MLX4_ROCE_MAX_GIDS];
+       struct mutex                    mutex;
+};
+
 #define MLX4_MAX_VLAN_NUM      128
 #define MLX4_VLAN_TABLE_SIZE   (MLX4_MAX_VLAN_NUM << 2)
 
@@ -758,6 +769,7 @@ struct mlx4_port_info {
        struct device_attribute port_mtu_attr;
        struct mlx4_mac_table   mac_table;
        struct mlx4_vlan_table  vlan_table;
+       struct mlx4_roce_gid_table gid_table;
        int                     base_qpn;
 };
 
@@ -788,10 +800,6 @@ enum {
        MLX4_USE_RR     = 1,
 };
 
-struct mlx4_roce_gid_entry {
-       u8 raw[16];
-};
-
 struct mlx4_priv {
        struct mlx4_dev         dev;
 
@@ -839,7 +847,6 @@ struct mlx4_priv {
        int                     fs_hash_mode;
        u8 virt2phys_pkey[MLX4_MFUNC_MAX][MLX4_MAX_PORTS][MLX4_MAX_PORT_PKEYS];
        __be64                  slave_node_guids[MLX4_MFUNC_MAX];
-       struct mlx4_roce_gid_entry roce_gids[MLX4_MAX_PORTS][MLX4_ROCE_MAX_GIDS];
 
        atomic_t                opreq_count;
        struct work_struct      opreq_task;
@@ -1140,6 +1147,8 @@ int mlx4_change_port_types(struct mlx4_dev *dev,
 
 void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table);
 void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table);
+void mlx4_init_roce_gid_table(struct mlx4_dev *dev,
+                             struct mlx4_roce_gid_table *table);
 void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan);
 int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);
 
@@ -1149,6 +1158,7 @@ int mlx4_get_slave_from_resource_id(struct mlx4_dev *dev,
                                    enum mlx4_resource resource_type,
                                    u64 resource_id, int *slave);
 void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave_id);
+void mlx4_reset_roce_gids(struct mlx4_dev *dev, int slave);
 int mlx4_init_resource_tracker(struct mlx4_dev *dev);
 
 void mlx4_free_resource_tracker(struct mlx4_dev *dev,
@@ -1195,6 +1205,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 cfcad26..5ec6f20 100644 (file)
@@ -75,6 +75,16 @@ void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table)
        table->total = 0;
 }
 
+void mlx4_init_roce_gid_table(struct mlx4_dev *dev,
+                             struct mlx4_roce_gid_table *table)
+{
+       int i;
+
+       mutex_init(&table->mutex);
+       for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++)
+               memset(table->roce_gids[i].raw, 0, MLX4_ROCE_GID_ENTRY_SIZE);
+}
+
 static int validate_index(struct mlx4_dev *dev,
                          struct mlx4_mac_table *table, int index)
 {
@@ -584,6 +594,84 @@ int mlx4_get_base_gid_ix(struct mlx4_dev *dev, int slave, int port)
 }
 EXPORT_SYMBOL_GPL(mlx4_get_base_gid_ix);
 
+static int mlx4_reset_roce_port_gids(struct mlx4_dev *dev, int slave,
+                                    int port, struct mlx4_cmd_mailbox *mailbox)
+{
+       struct mlx4_roce_gid_entry *gid_entry_mbox;
+       struct mlx4_priv *priv = mlx4_priv(dev);
+       int num_gids, base, offset;
+       int i, err;
+
+       num_gids = mlx4_get_slave_num_gids(dev, slave, port);
+       base = mlx4_get_base_gid_ix(dev, slave, port);
+
+       memset(mailbox->buf, 0, MLX4_MAILBOX_SIZE);
+
+       mutex_lock(&(priv->port[port].gid_table.mutex));
+       /* Zero-out gids belonging to that slave in the port GID table */
+       for (i = 0, offset = base; i < num_gids; offset++, i++)
+               memcpy(priv->port[port].gid_table.roce_gids[offset].raw,
+                      zgid_entry.raw, MLX4_ROCE_GID_ENTRY_SIZE);
+
+       /* Now, copy roce port gids table to mailbox for passing to FW */
+       gid_entry_mbox = (struct mlx4_roce_gid_entry *)mailbox->buf;
+       for (i = 0; i < MLX4_ROCE_MAX_GIDS; gid_entry_mbox++, i++)
+               memcpy(gid_entry_mbox->raw,
+                      priv->port[port].gid_table.roce_gids[i].raw,
+                      MLX4_ROCE_GID_ENTRY_SIZE);
+
+       err = mlx4_cmd(dev, mailbox->dma,
+                      ((u32)port) | (MLX4_SET_PORT_GID_TABLE << 8), 1,
+                      MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
+                      MLX4_CMD_NATIVE);
+       mutex_unlock(&(priv->port[port].gid_table.mutex));
+       return err;
+}
+
+
+void mlx4_reset_roce_gids(struct mlx4_dev *dev, int slave)
+{
+       struct mlx4_active_ports actv_ports;
+       struct mlx4_cmd_mailbox *mailbox;
+       int num_eth_ports, err;
+       int i;
+
+       if (slave < 0 || slave > dev->num_vfs)
+               return;
+
+       actv_ports = mlx4_get_active_ports(dev, slave);
+
+       for (i = 0, num_eth_ports = 0; i < dev->caps.num_ports; i++) {
+               if (test_bit(i, actv_ports.ports)) {
+                       if (dev->caps.port_type[i + 1] != MLX4_PORT_TYPE_ETH)
+                               continue;
+                       num_eth_ports++;
+               }
+       }
+
+       if (!num_eth_ports)
+               return;
+
+       /* have ETH ports.  Alloc mailbox for SET_PORT command */
+       mailbox = mlx4_alloc_cmd_mailbox(dev);
+       if (IS_ERR(mailbox))
+               return;
+
+       for (i = 0; i < dev->caps.num_ports; i++) {
+               if (test_bit(i, actv_ports.ports)) {
+                       if (dev->caps.port_type[i + 1] != MLX4_PORT_TYPE_ETH)
+                               continue;
+                       err = mlx4_reset_roce_port_gids(dev, slave, i + 1, mailbox);
+                       if (err)
+                               mlx4_warn(dev, "Could not reset ETH port GID table for slave %d, port %d (%d)\n",
+                                         slave, i + 1, err);
+               }
+       }
+
+       mlx4_free_cmd_mailbox(dev, mailbox);
+       return;
+}
+
 static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
                                u8 op_mod, struct mlx4_cmd_mailbox *inbox)
 {
@@ -692,10 +780,12 @@ static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
                        /* 2. Check that do not have duplicates in OTHER
                         *    entries in the port GID table
                         */
+
+                       mutex_lock(&(priv->port[port].gid_table.mutex));
                        for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++) {
                                if (i >= base && i < base + num_gids)
                                        continue; /* don't compare to slave's current gids */
-                               gid_entry_tbl = &priv->roce_gids[port - 1][i];
+                               gid_entry_tbl = &priv->port[port].gid_table.roce_gids[i];
                                if (!memcmp(gid_entry_tbl->raw, zgid_entry.raw, sizeof(zgid_entry)))
                                        continue;
                                gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf);
@@ -709,6 +799,7 @@ static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
                                                mlx4_warn(dev, "requested gid entry for slave:%d "
                                                          "is a duplicate of gid at index %d\n",
                                                          slave, i);
+                                               mutex_unlock(&(priv->port[port].gid_table.mutex));
                                                return -EINVAL;
                                        }
                                }
@@ -717,16 +808,24 @@ static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
                        /* insert slave GIDs with memcpy, starting at slave's base index */
                        gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf);
                        for (i = 0, offset = base; i < num_gids; gid_entry_mbox++, offset++, i++)
-                               memcpy(priv->roce_gids[port - 1][offset].raw, gid_entry_mbox->raw, 16);
+                               memcpy(priv->port[port].gid_table.roce_gids[offset].raw,
+                                      gid_entry_mbox->raw, MLX4_ROCE_GID_ENTRY_SIZE);
 
                        /* Now, copy roce port gids table to current mailbox for passing to FW */
                        gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf);
                        for (i = 0; i < MLX4_ROCE_MAX_GIDS; gid_entry_mbox++, i++)
-                               memcpy(gid_entry_mbox->raw, priv->roce_gids[port - 1][i].raw, 16);
-
-                       break;
+                               memcpy(gid_entry_mbox->raw,
+                                      priv->port[port].gid_table.roce_gids[i].raw,
+                                      MLX4_ROCE_GID_ENTRY_SIZE);
+
+                       err = mlx4_cmd(dev, inbox->dma, in_mod & 0xffff, op_mod,
+                                      MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
+                                      MLX4_CMD_NATIVE);
+                       mutex_unlock(&(priv->port[port].gid_table.mutex));
+                       return err;
                }
-               return mlx4_cmd(dev, inbox->dma, in_mod, op_mod,
+
+               return mlx4_cmd(dev, inbox->dma, in_mod & 0xffff, op_mod,
                                MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
                                MLX4_CMD_NATIVE);
        }
@@ -1099,13 +1198,17 @@ int mlx4_get_slave_from_roce_gid(struct mlx4_dev *dev, int port, u8 *gid,
        num_vfs = bitmap_weight(slaves_pport.slaves, dev->num_vfs + 1) - 1;
 
        for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++) {
-               if (!memcmp(priv->roce_gids[port - 1][i].raw, gid, 16)) {
+               if (!memcmp(priv->port[port].gid_table.roce_gids[i].raw, gid,
+                           MLX4_ROCE_GID_ENTRY_SIZE)) {
                        found_ix = i;
                        break;
                }
        }
 
        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 +1221,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;
@@ -1182,7 +1287,8 @@ int mlx4_get_roce_gid_from_slave(struct mlx4_dev *dev, int port, int slave_id,
        if (!mlx4_is_master(dev))
                return -EINVAL;
 
-       memcpy(gid, priv->roce_gids[port - 1][slave_id].raw, 16);
+       memcpy(gid, priv->port[port].gid_table.roce_gids[slave_id].raw,
+              MLX4_ROCE_GID_ENTRY_SIZE);
        return 0;
 }
 EXPORT_SYMBOL(mlx4_get_roce_gid_from_slave);
index 61d64eb..fbd32af 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 3b5f53e..f16e539 100644 (file)
@@ -586,6 +586,7 @@ void mlx4_free_resource_tracker(struct mlx4_dev *dev,
                        }
                        /* free master's vlans */
                        i = dev->caps.function;
+                       mlx4_reset_roce_gids(dev, i);
                        mutex_lock(&priv->mfunc.master.res_tracker.slave_list[i].mutex);
                        rem_slave_vlans(dev, i);
                        mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[i].mutex);
@@ -3733,6 +3734,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 +3788,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 +3896,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,
@@ -4604,7 +4682,7 @@ static void rem_slave_xrcdns(struct mlx4_dev *dev, int slave)
 void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
-
+       mlx4_reset_roce_gids(dev, slave);
        mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
        rem_slave_vlans(dev, slave);
        rem_slave_macs(dev, slave);
index 7b52a88..f785d01 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 a51fe18..561cb11 100644 (file)
@@ -1020,6 +1020,7 @@ static int qlcnic_dcb_peer_app_info(struct net_device *netdev,
        struct qlcnic_dcb_cee *peer;
        int i;
 
+       memset(info, 0, sizeof(*info));
        *app_count = 0;
 
        if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))
index dbf7539..7e55e88 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 0638c18..6afe9c1 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 6203c7d..4501964 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 c4da7a2..58c3569 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 e896dbb..2686bb5 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 838cb9f..1860932 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 4d989ff..bb9b5b8 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 27e8c82..82a9a98 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 01af2cb..43ccb4a 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 5a89acb..56f8bf5 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 32d969e..89b83e5 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 d1b4dca..bcaa41a 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 d940034..0f4841d 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 df8d383..b9ac20f 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 36aa109..c331b7e 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 31e55fb..7918d51 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 753a8c2..d53e299 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 ff111a8..3381c4f 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 9c4defd..5f1a225 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 5ad971a..d849684 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 1b6d09a..3bc079a 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 0ce6066..4987a1c 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 cc70ecf..ad4a94e 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 33008c1..ce4989b 100644 (file)
@@ -1724,6 +1724,7 @@ static int team_change_mtu(struct net_device *dev, int new_mtu)
         * to traverse list in reverse under rcu_read_lock
         */
        mutex_lock(&team->lock);
+       team->port_mtu_change_allowed = true;
        list_for_each_entry(port, &team->port_list, list) {
                err = dev_set_mtu(port->dev, new_mtu);
                if (err) {
@@ -1732,6 +1733,7 @@ static int team_change_mtu(struct net_device *dev, int new_mtu)
                        goto unwind;
                }
        }
+       team->port_mtu_change_allowed = false;
        mutex_unlock(&team->lock);
 
        dev->mtu = new_mtu;
@@ -1741,6 +1743,7 @@ static int team_change_mtu(struct net_device *dev, int new_mtu)
 unwind:
        list_for_each_entry_continue_reverse(port, &team->port_list, list)
                dev_set_mtu(port->dev, dev->mtu);
+       team->port_mtu_change_allowed = false;
        mutex_unlock(&team->lock);
 
        return err;
@@ -2834,8 +2837,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,
@@ -2849,7 +2854,9 @@ static int team_device_event(struct notifier_block *unused,
                break;
        case NETDEV_PRECHANGEMTU:
                /* Forbid to change mtu of underlaying device */
-               return NOTIFY_BAD;
+               if (!port->team->port_mtu_change_allowed)
+                       return NOTIFY_BAD;
+               break;
        case NETDEV_PRE_TYPE_CHANGE:
                /* Forbid to change type of underlaying device */
                return NOTIFY_BAD;
index c9f3281..2e025dd 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 549dbac..9a2bd11 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 421934c..973275f 100644 (file)
@@ -59,6 +59,8 @@
 #define USB_PRODUCT_IPHONE_3GS  0x1294
 #define USB_PRODUCT_IPHONE_4   0x1297
 #define USB_PRODUCT_IPAD 0x129a
+#define USB_PRODUCT_IPAD_2     0x12a2
+#define USB_PRODUCT_IPAD_3     0x12a6
 #define USB_PRODUCT_IPAD_MINI    0x12ab
 #define USB_PRODUCT_IPHONE_4_VZW 0x129c
 #define USB_PRODUCT_IPHONE_4S  0x12a0
@@ -106,6 +108,14 @@ static struct usb_device_id ipheth_table[] = {
                USB_VENDOR_APPLE, USB_PRODUCT_IPAD,
                IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
                IPHETH_USBINTF_PROTO) },
+       { USB_DEVICE_AND_INTERFACE_INFO(
+               USB_VENDOR_APPLE, USB_PRODUCT_IPAD_2,
+               IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
+               IPHETH_USBINTF_PROTO) },
+       { USB_DEVICE_AND_INTERFACE_INFO(
+               USB_VENDOR_APPLE, USB_PRODUCT_IPAD_3,
+               IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
+               IPHETH_USBINTF_PROTO) },
        { USB_DEVICE_AND_INTERFACE_INFO(
                USB_VENDOR_APPLE, USB_PRODUCT_IPAD_MINI,
                IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
index e3458e3..dc4bf06 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,32 @@ 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, 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(0x1199, 0x9053, 8)},    /* Sierra Wireless Modem */
+       {QMI_FIXED_INTF(0x1199, 0x9054, 8)},    /* Sierra Wireless Modem */
+       {QMI_FIXED_INTF(0x1199, 0x9055, 8)},    /* Netgear AirCard 341U */
+       {QMI_FIXED_INTF(0x1199, 0x9056, 8)},    /* Sierra Wireless Modem */
+       {QMI_FIXED_INTF(0x1199, 0x9061, 8)},    /* Sierra Wireless Modem */
        {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 7b68746..8a852b5 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 82355d5..4dbb2ed 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 a0398fe..be3eb2a 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 6d47783..ba502a2 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 44d7449..3ba03dd 100644 (file)
@@ -251,7 +251,6 @@ struct ath_atx_tid {
 
        s8 bar_index;
        bool sched;
-       bool paused;
        bool active;
 };
 
index d76e6e0..ffca918 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 f46cd02..5627917 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 cbbb02a..36ae649 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 25304ad..914dbc6 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 6c9accd..19df969 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 87cbec4..66acb2c 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 df130ef..c7c9f15 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 afb3d15..be19852 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 fa858d5..0489314 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 9426905..d73a89e 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 f0cebf1..8735ef1 100644 (file)
@@ -826,7 +826,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
        if (ret)
                goto out_remove_mac;
 
-       if (!mvm->bf_allowed_vif &&
+       if (!mvm->bf_allowed_vif && false &&
            vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
            mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED){
                mvm->bf_allowed_vif = mvmvif;
@@ -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 d564233..f1ec098 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 9f52c5b..e1c8388 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 c91dc84..c28de54 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 d619851..2180902 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 dcfd6d8..2365553 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 ddeb5a7..a87ee9b 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 06ef47c..5b4c225 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 68b5c7e..07cb06d 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 36b48be..2b3c78b 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 630a3fc..0d4a285 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 ef05c5c..20e9def 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 7666540..7367208 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 6d4ee22..32e969d 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 9bcf2cf..5aeb894 100644 (file)
@@ -364,7 +364,7 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
 
                memset(r, 0, sizeof(*r));
                /*
-                * Get optional "interrupts-names" property to add a name
+                * Get optional "interrupt-names" property to add a name
                 * to the resource.
                 */
                of_property_read_string_index(dev, "interrupt-names", index,
@@ -379,6 +379,32 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
 }
 EXPORT_SYMBOL_GPL(of_irq_to_resource);
 
+/**
+ * of_irq_get - Decode a node's IRQ and return it as a Linux irq number
+ * @dev: pointer to device tree node
+ * @index: zero-based index of the irq
+ *
+ * Returns Linux irq number on success, or -EPROBE_DEFER if the irq domain
+ * is not yet created.
+ *
+ */
+int of_irq_get(struct device_node *dev, int index)
+{
+       int rc;
+       struct of_phandle_args oirq;
+       struct irq_domain *domain;
+
+       rc = of_irq_parse_one(dev, index, &oirq);
+       if (rc)
+               return rc;
+
+       domain = irq_find_host(oirq.np);
+       if (!domain)
+               return -EPROBE_DEFER;
+
+       return irq_create_of_mapping(&oirq);
+}
+
 /**
  * of_irq_count - Count the number of IRQs a node uses
  * @dev: pointer to device tree node
index 404d1da..bd47fbc 100644 (file)
@@ -168,7 +168,9 @@ struct platform_device *of_device_alloc(struct device_node *np,
                        rc = of_address_to_resource(np, i, res);
                        WARN_ON(rc);
                }
-               WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq);
+               if (of_irq_to_resource_table(np, res, num_irq) != num_irq)
+                       pr_debug("not all legacy IRQ resources mapped for %s\n",
+                                np->name);
        }
 
        dev->dev.of_node = of_node_get(np);
index ae44500..fe70b86 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
+#include <linux/of_platform.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
@@ -427,6 +428,36 @@ static void __init of_selftest_match_node(void)
        }
 }
 
+static void __init of_selftest_platform_populate(void)
+{
+       int irq;
+       struct device_node *np;
+       struct platform_device *pdev;
+
+       np = of_find_node_by_path("/testcase-data");
+       of_platform_populate(np, of_default_bus_match_table, NULL, NULL);
+
+       /* Test that a missing irq domain returns -EPROBE_DEFER */
+       np = of_find_node_by_path("/testcase-data/testcase-device1");
+       pdev = of_find_device_by_node(np);
+       if (!pdev)
+               selftest(0, "device 1 creation failed\n");
+       irq = platform_get_irq(pdev, 0);
+       if (irq != -EPROBE_DEFER)
+               selftest(0, "device deferred probe failed - %d\n", irq);
+
+       /* Test that a parsing failure does not return -EPROBE_DEFER */
+       np = of_find_node_by_path("/testcase-data/testcase-device2");
+       pdev = of_find_device_by_node(np);
+       if (!pdev)
+               selftest(0, "device 2 creation failed\n");
+       irq = platform_get_irq(pdev, 0);
+       if (irq >= 0 || irq == -EPROBE_DEFER)
+               selftest(0, "device parsing error failed - %d\n", irq);
+
+       selftest(1, "passed");
+}
+
 static int __init of_selftest(void)
 {
        struct device_node *np;
@@ -445,6 +476,7 @@ static int __init of_selftest(void)
        of_selftest_parse_interrupts();
        of_selftest_parse_interrupts_extended();
        of_selftest_match_node();
+       of_selftest_platform_populate();
        pr_info("end of selftest - %i passed, %i failed\n",
                selftest_results.passed, selftest_results.failed);
        return 0;
index c843720..da4695f 100644 (file)
                                                      <&test_intmap1 1 2>;
                        };
                };
+
+               testcase-device1 {
+                       compatible = "testcase-device";
+                       interrupt-parent = <&test_intc0>;
+                       interrupts = <1>;
+               };
+
+               testcase-device2 {
+                       compatible = "testcase-device";
+                       interrupt-parent = <&test_intc2>;
+                       interrupts = <1>; /* invalid specifier - too short */
+               };
        };
+
 };
index d3d1cfd..e384e25 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 5849927..6efc2ec 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 7325d43..759475e 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 92ed4b2..c862f9c 100644 (file)
@@ -64,7 +64,6 @@ struct as3722_pin_function {
 };
 
 struct as3722_gpio_pin_control {
-       bool enable_gpio_invert;
        unsigned mode_prop;
        int io_function;
 };
@@ -320,10 +319,8 @@ static int as3722_pinctrl_gpio_set_direction(struct pinctrl_dev *pctldev,
                return mode;
        }
 
-       if (as_pci->gpio_control[offset].enable_gpio_invert)
-               mode |= AS3722_GPIO_INV;
-
-       return as3722_write(as3722, AS3722_GPIOn_CONTROL_REG(offset), mode);
+       return as3722_update_bits(as3722, AS3722_GPIOn_CONTROL_REG(offset),
+                               AS3722_GPIO_MODE_MASK, mode);
 }
 
 static const struct pinmux_ops as3722_pinmux_ops = {
@@ -496,10 +493,18 @@ static void as3722_gpio_set(struct gpio_chip *chip, unsigned offset,
 {
        struct as3722_pctrl_info *as_pci = to_as_pci(chip);
        struct as3722 *as3722 = as_pci->as3722;
-       int en_invert = as_pci->gpio_control[offset].enable_gpio_invert;
+       int en_invert;
        u32 val;
        int ret;
 
+       ret = as3722_read(as3722, AS3722_GPIOn_CONTROL_REG(offset), &val);
+       if (ret < 0) {
+               dev_err(as_pci->dev,
+                       "GPIO_CONTROL%d_REG read failed: %d\n", offset, ret);
+               return;
+       }
+       en_invert = !!(val & AS3722_GPIO_INV);
+
        if (value)
                val = (en_invert) ? 0 : AS3722_GPIOn_SIGNAL(offset);
        else
index 81075f2..2960557 100644 (file)
@@ -810,6 +810,7 @@ static const struct pinconf_ops pcs_pinconf_ops = {
 static int pcs_add_pin(struct pcs_device *pcs, unsigned offset,
                unsigned pin_pos)
 {
+       struct pcs_soc_data *pcs_soc = &pcs->socdata;
        struct pinctrl_pin_desc *pin;
        struct pcs_name *pn;
        int i;
@@ -821,6 +822,18 @@ static int pcs_add_pin(struct pcs_device *pcs, unsigned offset,
                return -ENOMEM;
        }
 
+       if (pcs_soc->irq_enable_mask) {
+               unsigned val;
+
+               val = pcs->read(pcs->base + offset);
+               if (val & pcs_soc->irq_enable_mask) {
+                       dev_dbg(pcs->dev, "irq enabled at boot for pin at %lx (%x), clearing\n",
+                               (unsigned long)pcs->res->start + offset, val);
+                       val &= ~pcs_soc->irq_enable_mask;
+                       pcs->write(val, pcs->base + offset);
+               }
+       }
+
        pin = &pcs->pins.pa[i];
        pn = &pcs->names[i];
        sprintf(pn->name, "%lx.%d",
index c5e0f69..26ca685 100644 (file)
@@ -629,9 +629,8 @@ static int tb10x_gpio_request_enable(struct pinctrl_dev *pctl,
         */
        for (i = 0; i < state->pinfuncgrpcnt; i++) {
                const struct tb10x_pinfuncgrp *pfg = &state->pingroups[i];
-               unsigned int port = pfg->port;
                unsigned int mode = pfg->mode;
-               int j;
+               int j, port = pfg->port;
 
                /*
                 * Skip pin groups which are always mapped and don't need
index 4809371..f5cd3f9 100644 (file)
@@ -4794,8 +4794,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
                FN_MSIOF0_SCK_B, 0,
                /* IP5_23_21 [3] */
                FN_WE1_N, FN_IERX, FN_CAN1_RX, FN_VI1_G4,
-               FN_VI1_G4_B, FN_VI2_R6, FN_SCIFA0_CTS_N_B,
-               FN_IERX_C, 0,
+               FN_VI1_G4_B, FN_VI2_R6, FN_SCIFA0_CTS_N_B, FN_IERX_C,
                /* IP5_20_18 [3] */
                FN_WE0_N, FN_IECLK, FN_CAN_CLK,
                FN_VI2_VSYNC_N, FN_SCIFA0_TXD_B, FN_VI2_VSYNC_N_B, 0, 0,
index 5186d70..7868bf3 100644 (file)
@@ -5288,7 +5288,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
                /* SEL_SCIF3 [2] */
                FN_SEL_SCIF3_0, FN_SEL_SCIF3_1, FN_SEL_SCIF3_2, FN_SEL_SCIF3_3,
                /* SEL_IEB [2] */
-               FN_SEL_IEB_0, FN_SEL_IEB_1, FN_SEL_IEB_2,
+               FN_SEL_IEB_0, FN_SEL_IEB_1, FN_SEL_IEB_2, 0,
                /* SEL_MMC [1] */
                FN_SEL_MMC_0, FN_SEL_MMC_1,
                /* SEL_SCIF5 [1] */
index 9802b67..2c61281 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 9f611cb..c31aa07 100644 (file)
@@ -83,8 +83,7 @@ static int pnpacpi_set_resources(struct pnp_dev *dev)
 {
        struct acpi_device *acpi_dev;
        acpi_handle handle;
-       struct acpi_buffer buffer;
-       int ret;
+       int ret = 0;
 
        pnp_dbg(&dev->dev, "set resources\n");
 
@@ -97,19 +96,26 @@ static int pnpacpi_set_resources(struct pnp_dev *dev)
        if (WARN_ON_ONCE(acpi_dev != dev->data))
                dev->data = acpi_dev;
 
-       ret = pnpacpi_build_resource_template(dev, &buffer);
-       if (ret)
-               return ret;
-       ret = pnpacpi_encode_resources(dev, &buffer);
-       if (ret) {
+       if (acpi_has_method(handle, METHOD_NAME__SRS)) {
+               struct acpi_buffer buffer;
+
+               ret = pnpacpi_build_resource_template(dev, &buffer);
+               if (ret)
+                       return ret;
+
+               ret = pnpacpi_encode_resources(dev, &buffer);
+               if (!ret) {
+                       acpi_status status;
+
+                       status = acpi_set_current_resources(handle, &buffer);
+                       if (ACPI_FAILURE(status))
+                               ret = -EIO;
+               }
                kfree(buffer.pointer);
-               return ret;
        }
-       if (ACPI_FAILURE(acpi_set_current_resources(handle, &buffer)))
-               ret = -EINVAL;
-       else if (acpi_bus_power_manageable(handle))
+       if (!ret && acpi_bus_power_manageable(handle))
                ret = acpi_bus_set_power(handle, ACPI_STATE_D0);
-       kfree(buffer.pointer);
+
        return ret;
 }
 
@@ -117,7 +123,7 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev)
 {
        struct acpi_device *acpi_dev;
        acpi_handle handle;
-       int ret;
+       acpi_status status;
 
        dev_dbg(&dev->dev, "disable resources\n");
 
@@ -128,13 +134,15 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev)
        }
 
        /* acpi_unregister_gsi(pnp_irq(dev, 0)); */
-       ret = 0;
        if (acpi_bus_power_manageable(handle))
                acpi_bus_set_power(handle, ACPI_STATE_D3_COLD);
-               /* continue even if acpi_bus_set_power() fails */
-       if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DIS", NULL, NULL)))
-               ret = -ENODEV;
-       return ret;
+
+       /* continue even if acpi_bus_set_power() fails */
+       status = acpi_evaluate_object(handle, "_DIS", NULL, NULL);
+       if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
+               return -ENODEV;
+
+       return 0;
 }
 
 #ifdef CONFIG_ACPI_SLEEP
index deb7f4b..438d4c7 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 3736bc4..ebf0d67 100644 (file)
@@ -335,7 +335,7 @@ static void quirk_amd_mmconfig_area(struct pnp_dev *dev)
 }
 #endif
 
-#ifdef CONFIG_X86
+#ifdef CONFIG_PCI
 /* Device IDs of parts that have 32KB MCH space */
 static const unsigned int mch_quirk_devices[] = {
        0x0154, /* Ivy Bridge */
@@ -440,7 +440,7 @@ static struct pnp_fixup pnp_fixups[] = {
 #ifdef CONFIG_AMD_NB
        {"PNP0c01", quirk_amd_mmconfig_area},
 #endif
-#ifdef CONFIG_X86
+#ifdef CONFIG_PCI
        {"PNP0c02", quirk_intel_mch},
 #endif
        {""}
index 6963bdf..6aea373 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 bd628a6..e5f13c4 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 5c8f822..4cdb64b 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 9f0ea6c..e3bf885 100644 (file)
@@ -541,18 +541,27 @@ static void chsc_process_sei_nt0(struct chsc_sei_nt0_area *sei_area)
 
 static void chsc_process_event_information(struct chsc_sei *sei, u64 ntsm)
 {
-       do {
+       static int ntsm_unsupported;
+
+       while (true) {
                memset(sei, 0, sizeof(*sei));
                sei->request.length = 0x0010;
                sei->request.code = 0x000e;
-               sei->ntsm = ntsm;
+               if (!ntsm_unsupported)
+                       sei->ntsm = ntsm;
 
                if (chsc(sei))
                        break;
 
                if (sei->response.code != 0x0001) {
-                       CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n",
-                                     sei->response.code);
+                       CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x, ntsm=%llx)\n",
+                                     sei->response.code, sei->ntsm);
+
+                       if (sei->response.code == 3 && sei->ntsm) {
+                               /* Fallback for old firmware. */
+                               ntsm_unsupported = 1;
+                               continue;
+                       }
                        break;
                }
 
@@ -568,7 +577,10 @@ static void chsc_process_event_information(struct chsc_sei *sei, u64 ntsm)
                        CIO_CRW_EVENT(2, "chsc: unhandled nt: %d\n", sei->nt);
                        break;
                }
-       } while (sei->u.nt0_area.flags & 0x80);
+
+               if (!(sei->u.nt0_area.flags & 0x80))
+                       break;
+       }
 }
 
 /*
index 7f0af4f..6fd7d40 100644 (file)
@@ -8293,7 +8293,6 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state)
 
        mpt2sas_base_free_resources(ioc);
        pci_save_state(pdev);
-       pci_disable_device(pdev);
        pci_set_power_state(pdev, device_state);
        return 0;
 }
index fe30ea9..109802f 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 1b68142..c341f85 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 16bfd50..db3b494 100644 (file)
@@ -750,8 +750,12 @@ static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity)
 
                vscsi->affinity_hint_set = true;
        } else {
-               for (i = 0; i < vscsi->num_queues; i++)
+               for (i = 0; i < vscsi->num_queues; i++) {
+                       if (!vscsi->req_vqs[i].vq)
+                               continue;
+
                        virtqueue_set_affinity(vscsi->req_vqs[i].vq, -1);
+               }
 
                vscsi->affinity_hint_set = false;
        }
index fc67f56..788ed9b 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 8afa5a4..10c65eb 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 713af48..f6759dc 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 b032e88..78c66e3 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 4eb9bf0..939edf4 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 171a71d..728bf7f 100644 (file)
@@ -139,6 +139,8 @@ static int daq700_ai_rinsn(struct comedi_device *dev,
        /* write channel to multiplexer */
        /* set mask scan bit high to disable scanning */
        outb(chan | 0x80, dev->iobase + CMD_R1);
+       /* mux needs 2us to really settle [Fred Brooks]. */
+       udelay(2);
 
        /* convert n samples */
        for (n = 0; n < insn->n; n++) {
index e2b4820..017d2f8 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 4144a75..c270c9a 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 575533f..a23f4f7 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 8c101cb..acc8184 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 b3d2cc7..4ba5692 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 11d0a9d..b7dd153 100644 (file)
@@ -171,7 +171,7 @@ inline int rtllib_put_snap(u8 *data, u16 h_proto)
        snap->oui[1] = oui[1];
        snap->oui[2] = oui[2];
 
-       *(u16 *)(data + SNAP_SIZE) = h_proto;
+       *(__be16 *)(data + SNAP_SIZE) = htons(h_proto);
 
        return SNAP_SIZE + sizeof(u16);
 }
index 57eca7a..4fe751f 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 c49160e..07e542e 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 3b6e535..7de79d5 100644 (file)
@@ -2218,6 +2218,7 @@ static void __exit speakup_exit(void)
        unregister_keyboard_notifier(&keyboard_notifier_block);
        unregister_vt_notifier(&vt_notifier_block);
        speakup_unregister_devsynth();
+       speakup_cancel_paste();
        del_timer(&cursor_timer);
        kthread_stop(speakup_task);
        speakup_task = NULL;
index f0fb003..ca04d36 100644 (file)
@@ -4,6 +4,10 @@
 #include <linux/sched.h>
 #include <linux/device.h> /* for dev_warn */
 #include <linux/selection.h>
+#include <linux/workqueue.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <asm/cmpxchg.h>
 
 #include "speakup.h"
 
@@ -121,31 +125,61 @@ int speakup_set_selection(struct tty_struct *tty)
        return 0;
 }
 
-/* TODO: move to some helper thread, probably.  That'd fix having to check for
- * in_atomic().  */
-int speakup_paste_selection(struct tty_struct *tty)
+struct speakup_paste_work {
+       struct work_struct work;
+       struct tty_struct *tty;
+};
+
+static void __speakup_paste_selection(struct work_struct *work)
 {
+       struct speakup_paste_work *spw =
+               container_of(work, struct speakup_paste_work, work);
+       struct tty_struct *tty = xchg(&spw->tty, NULL);
        struct vc_data *vc = (struct vc_data *) tty->driver_data;
        int pasted = 0, count;
+       struct tty_ldisc *ld;
        DECLARE_WAITQUEUE(wait, current);
+
+       ld = tty_ldisc_ref_wait(tty);
+       tty_buffer_lock_exclusive(&vc->port);
+
        add_wait_queue(&vc->paste_wait, &wait);
        while (sel_buffer && sel_buffer_lth > pasted) {
                set_current_state(TASK_INTERRUPTIBLE);
                if (test_bit(TTY_THROTTLED, &tty->flags)) {
-                       if (in_atomic())
-                               /* if we are in an interrupt handler, abort */
-                               break;
                        schedule();
                        continue;
                }
                count = sel_buffer_lth - pasted;
-               count = min_t(int, count, tty->receive_room);
-               tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted,
-                       NULL, count);
+               count = tty_ldisc_receive_buf(ld, sel_buffer + pasted, NULL,
+                                             count);
                pasted += count;
        }
        remove_wait_queue(&vc->paste_wait, &wait);
        current->state = TASK_RUNNING;
+
+       tty_buffer_unlock_exclusive(&vc->port);
+       tty_ldisc_deref(ld);
+       tty_kref_put(tty);
+}
+
+static struct speakup_paste_work speakup_paste_work = {
+       .work = __WORK_INITIALIZER(speakup_paste_work.work,
+                                  __speakup_paste_selection)
+};
+
+int speakup_paste_selection(struct tty_struct *tty)
+{
+       if (cmpxchg(&speakup_paste_work.tty, NULL, tty) != NULL)
+               return -EBUSY;
+
+       tty_kref_get(tty);
+       schedule_work_on(WORK_CPU_UNBOUND, &speakup_paste_work.work);
        return 0;
 }
 
+void speakup_cancel_paste(void)
+{
+       cancel_work_sync(&speakup_paste_work.work);
+       tty_kref_put(speakup_paste_work.tty);
+}
index a7bccee..898dce5 100644 (file)
@@ -75,6 +75,7 @@ extern void synth_buffer_clear(void);
 extern void speakup_clear_selection(void);
 extern int speakup_set_selection(struct tty_struct *tty);
 extern int speakup_paste_selection(struct tty_struct *tty);
+extern void speakup_cancel_paste(void);
 extern void speakup_register_devsynth(void);
 extern void speakup_unregister_devsynth(void);
 extern void synth_write(const char *buf, size_t count);
index c7f014e..5079dbd 100644 (file)
@@ -60,15 +60,15 @@ static struct kobj_attribute vol_attribute =
        __ATTR(vol, S_IWUGO|S_IRUGO, spk_var_show, spk_var_store);
 
 static struct kobj_attribute delay_time_attribute =
-       __ATTR(delay_time, S_IRUSR|S_IRUGO, spk_var_show, spk_var_store);
+       __ATTR(delay_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
 static struct kobj_attribute direct_attribute =
        __ATTR(direct, S_IWUGO|S_IRUGO, spk_var_show, spk_var_store);
 static struct kobj_attribute full_time_attribute =
-       __ATTR(full_time, S_IRUSR|S_IRUGO, spk_var_show, spk_var_store);
+       __ATTR(full_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
 static struct kobj_attribute jiffy_delta_attribute =
-       __ATTR(jiffy_delta, S_IRUSR|S_IRUGO, spk_var_show, spk_var_store);
+       __ATTR(jiffy_delta, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
 static struct kobj_attribute trigger_time_attribute =
-       __ATTR(trigger_time, S_IRUSR|S_IRUGO, spk_var_show, spk_var_store);
+       __ATTR(trigger_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
 
 /*
  * Create a group of attributes so that we can create and destroy them all
index 94f9e3a..0ff7fda 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 41fe8a0..fe9d129 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 0e1bf88..2d4bd39 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 f1d30f6..143deb6 100644 (file)
@@ -60,6 +60,7 @@ void tty_buffer_lock_exclusive(struct tty_port *port)
        atomic_inc(&buf->priority);
        mutex_lock(&buf->lock);
 }
+EXPORT_SYMBOL_GPL(tty_buffer_lock_exclusive);
 
 void tty_buffer_unlock_exclusive(struct tty_port *port)
 {
@@ -73,6 +74,7 @@ void tty_buffer_unlock_exclusive(struct tty_port *port)
        if (restart)
                queue_work(system_unbound_wq, &buf->work);
 }
+EXPORT_SYMBOL_GPL(tty_buffer_unlock_exclusive);
 
 /**
  *     tty_buffer_space_avail  -       return unused buffer space
@@ -255,16 +257,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 +449,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 +525,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 888881e..4aeb100 100644 (file)
@@ -1822,10 +1822,13 @@ int usb_runtime_suspend(struct device *dev)
        if (status == -EAGAIN || status == -EBUSY)
                usb_mark_last_busy(udev);
 
-       /* The PM core reacts badly unless the return code is 0,
-        * -EAGAIN, or -EBUSY, so always return -EBUSY on an error.
+       /*
+        * The PM core reacts badly unless the return code is 0,
+        * -EAGAIN, or -EBUSY, so always return -EBUSY on an error
+        * (except for root hubs, because they don't suspend through
+        * an upstream port like other USB devices).
         */
-       if (status != 0)
+       if (status != 0 && udev->parent)
                return -EBUSY;
        return status;
 }
index 090469e..229a73f 100644 (file)
@@ -1691,8 +1691,19 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
         */
        pm_runtime_set_autosuspend_delay(&hdev->dev, 0);
 
-       /* Hubs have proper suspend/resume support. */
-       usb_enable_autosuspend(hdev);
+       /*
+        * Hubs have proper suspend/resume support, except for root hubs
+        * where the controller driver doesn't have bus_suspend and
+        * bus_resume methods.
+        */
+       if (hdev->parent) {             /* normal device */
+               usb_enable_autosuspend(hdev);
+       } else {                        /* root hub */
+               const struct hc_driver *drv = bus_to_hcd(hdev->bus)->driver;
+
+               if (drv->bus_suspend && drv->bus_resume)
+                       usb_enable_autosuspend(hdev);
+       }
 
        if (hdev->level == MAX_TOPO_LEVEL) {
                dev_err(&intf->dev,
index f605ad8..cfd18bc 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 6f2c8d3..cf2734b 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 c81c872..cd871b8 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 90879e9..bb15096 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 9250cad..4550ce0 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 00661d3..4a6d3dd 100644 (file)
@@ -847,6 +847,13 @@ void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev)
        bool            ehci_found = false;
        struct pci_dev  *companion = NULL;
 
+       /* Sony VAIO t-series with subsystem device ID 90a8 is not capable of
+        * switching ports from EHCI to xHCI
+        */
+       if (xhci_pdev->subsystem_vendor == PCI_VENDOR_ID_SONY &&
+           xhci_pdev->subsystem_device == 0x90a8)
+               return;
+
        /* make sure an intel EHCI controller exists */
        for_each_pci_dev(companion) {
                if (companion->class == PCI_CLASS_SERIAL_USB_EHCI &&
index c089668..b1a8a5f 100644 (file)
@@ -1822,6 +1822,16 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
                kfree(cur_cd);
        }
 
+       num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
+       for (i = 0; i < num_ports; i++) {
+               struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table;
+               for (j = 0; j < XHCI_MAX_INTERVAL; j++) {
+                       struct list_head *ep = &bwt->interval_bw[j].endpoints;
+                       while (!list_empty(ep))
+                               list_del_init(ep->next);
+               }
+       }
+
        for (i = 1; i < MAX_HC_SLOTS; ++i)
                xhci_free_virt_device(xhci, i);
 
@@ -1857,16 +1867,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
        if (!xhci->rh_bw)
                goto no_bw;
 
-       num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
-       for (i = 0; i < num_ports; i++) {
-               struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table;
-               for (j = 0; j < XHCI_MAX_INTERVAL; j++) {
-                       struct list_head *ep = &bwt->interval_bw[j].endpoints;
-                       while (!list_empty(ep))
-                               list_del_init(ep->next);
-               }
-       }
-
        for (i = 0; i < num_ports; i++) {
                struct xhci_tt_bw_info *tt, *n;
                list_for_each_entry_safe(tt, n, &xhci->rh_bw[i].tts, tt_list) {
index c47e5a6..d03fadd 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 7c6e1de..edf3b12 100644 (file)
@@ -580,6 +580,8 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_TIAO_UMPA_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+       { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        /*
         * ELV devices:
         */
index 993c93d..500474c 100644 (file)
  */
 #define FTDI_TIAO_UMPA_PID     0x8a98  /* TIAO/DIYGADGET USB Multi-Protocol Adapter */
 
+/*
+ * NovaTech product ids (FTDI_VID)
+ */
+#define FTDI_NT_ORIONLXM_PID   0x7c90  /* OrionLXm Substation Automation Platform */
+
 
 /********************************/
 /** third-party VID/PID combos **/
index df90dae..c0a42e9 100644 (file)
@@ -821,7 +821,7 @@ static int build_i2c_fw_hdr(__u8 *header, struct device *dev)
        firmware_rec =  (struct ti_i2c_firmware_rec*)i2c_header->Data;
 
        i2c_header->Type        = I2C_DESC_TYPE_FIRMWARE_BLANK;
-       i2c_header->Size        = (__u16)buffer_size;
+       i2c_header->Size        = cpu_to_le16(buffer_size);
        i2c_header->CheckSum    = cs;
        firmware_rec->Ver_Major = OperationalMajorVersion;
        firmware_rec->Ver_Minor = OperationalMinorVersion;
index 51f83fb..6f6a856 100644 (file)
@@ -594,7 +594,7 @@ struct edge_boot_descriptor {
 
 struct ti_i2c_desc {
        __u8    Type;                   // Type of descriptor
-       __u16   Size;                   // Size of data only not including header
+       __le16  Size;                   // Size of data only not including header
        __u8    CheckSum;               // Checksum (8 bit sum of data only)
        __u8    Data[0];                // Data starts here
 } __attribute__((packed));
index f213ee9..948a19f 100644 (file)
@@ -161,6 +161,7 @@ static void option_instat_callback(struct urb *urb);
 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED        0x9000
 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED        0x9001
 #define NOVATELWIRELESS_PRODUCT_E362           0x9010
+#define NOVATELWIRELESS_PRODUCT_E371           0x9011
 #define NOVATELWIRELESS_PRODUCT_G2             0xA010
 #define NOVATELWIRELESS_PRODUCT_MC551          0xB001
 
@@ -1012,6 +1013,7 @@ static const struct usb_device_id option_ids[] = {
        /* Novatel Ovation MC551 a.k.a. Verizon USB551L */
        { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E371, 0xff, 0xff, 0xff) },
 
        { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
        { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
index 7ed681a..6c0a542 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 4ef2a80..008d805 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 f4a8229..174a447 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 96109a9..84b4bfb 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 6d589f2..895ac7d 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 1c8c6cc..4b0eff6 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 be75b50..590b55f 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 ef943df..03a3beb 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 12a3de0..a0ed6c7 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -112,6 +112,11 @@ struct kioctx {
 
        struct work_struct      free_work;
 
+       /*
+        * signals when all in-flight requests are done
+        */
+       struct completion *requests_done;
+
        struct {
                /*
                 * This counts the number of available slots in the ringbuffer,
@@ -508,6 +513,10 @@ static void free_ioctx_reqs(struct percpu_ref *ref)
 {
        struct kioctx *ctx = container_of(ref, struct kioctx, reqs);
 
+       /* At this point we know that there are no any in-flight requests */
+       if (ctx->requests_done)
+               complete(ctx->requests_done);
+
        INIT_WORK(&ctx->free_work, free_ioctx);
        schedule_work(&ctx->free_work);
 }
@@ -718,7 +727,8 @@ err:
  *     when the processes owning a context have all exited to encourage
  *     the rapid destruction of the kioctx.
  */
-static void kill_ioctx(struct mm_struct *mm, struct kioctx *ctx)
+static void kill_ioctx(struct mm_struct *mm, struct kioctx *ctx,
+               struct completion *requests_done)
 {
        if (!atomic_xchg(&ctx->dead, 1)) {
                struct kioctx_table *table;
@@ -747,7 +757,11 @@ static void kill_ioctx(struct mm_struct *mm, struct kioctx *ctx)
                if (ctx->mmap_size)
                        vm_munmap(ctx->mmap_base, ctx->mmap_size);
 
+               ctx->requests_done = requests_done;
                percpu_ref_kill(&ctx->users);
+       } else {
+               if (requests_done)
+                       complete(requests_done);
        }
 }
 
@@ -809,7 +823,7 @@ void exit_aio(struct mm_struct *mm)
                 */
                ctx->mmap_size = 0;
 
-               kill_ioctx(mm, ctx);
+               kill_ioctx(mm, ctx, NULL);
        }
 }
 
@@ -1185,7 +1199,7 @@ SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp)
        if (!IS_ERR(ioctx)) {
                ret = put_user(ioctx->user_id, ctxp);
                if (ret)
-                       kill_ioctx(current->mm, ioctx);
+                       kill_ioctx(current->mm, ioctx, NULL);
                percpu_ref_put(&ioctx->users);
        }
 
@@ -1203,8 +1217,22 @@ SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx)
 {
        struct kioctx *ioctx = lookup_ioctx(ctx);
        if (likely(NULL != ioctx)) {
-               kill_ioctx(current->mm, ioctx);
+               struct completion requests_done =
+                       COMPLETION_INITIALIZER_ONSTACK(requests_done);
+
+               /* Pass requests_done to kill_ioctx() where it can be set
+                * in a thread-safe way. If we try to set it here then we have
+                * a race condition if two io_destroy() called simultaneously.
+                */
+               kill_ioctx(current->mm, ioctx, &requests_done);
                percpu_ref_put(&ioctx->users);
+
+               /* Wait until all IO for the context are done. Otherwise kernel
+                * keep using user-space buffers even if user thinks the context
+                * is destroyed.
+                */
+               wait_for_completion(&requests_done);
+
                return 0;
        }
        pr_debug("EINVAL: io_destroy: invalid context id\n");
@@ -1299,10 +1327,8 @@ rw_common:
                                                &iovec, compat)
                        : aio_setup_single_vector(req, rw, buf, &nr_segs,
                                                  iovec);
-               if (ret)
-                       return ret;
-
-               ret = rw_verify_area(rw, file, &req->ki_pos, req->ki_nbytes);
+               if (!ret)
+                       ret = rw_verify_area(rw, file, &req->ki_pos, req->ki_nbytes);
                if (ret < 0) {
                        if (iovec != &inline_vec)
                                kfree(iovec);
index 2caf36a..cc87c1a 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 2ad7de9..2f6d7b1 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 eb6537a..fd38b50 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 2e5e648..c561b62 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 766410a..c29d6ae 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 0b0728e..233c6f9 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 fdf941b..a822a6e 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 d94ba0d..1913988 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 7866cd0..ead05cc 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 aadc2b6..a22d667 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 40707d8..be2bea8 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 476f3eb..238b7aa 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 a0b0855..205e0d5 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 5b4e035..4219835 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 13f8bde..96d513e 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 a257ed8..7aa5c75 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 8d61169..754dcf2 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 2040275..e19d4c0 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 e01ea4a..5e9a80c 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 6a5f04a..95dcd1d 100644 (file)
@@ -62,7 +62,7 @@ struct kernfs_root *kernfs_root_from_sb(struct super_block *sb)
        return NULL;
 }
 
-static int kernfs_fill_super(struct super_block *sb)
+static int kernfs_fill_super(struct super_block *sb, unsigned long magic)
 {
        struct kernfs_super_info *info = kernfs_info(sb);
        struct inode *inode;
@@ -70,7 +70,7 @@ static int kernfs_fill_super(struct super_block *sb)
 
        sb->s_blocksize = PAGE_CACHE_SIZE;
        sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
-       sb->s_magic = SYSFS_MAGIC;
+       sb->s_magic = magic;
        sb->s_op = &kernfs_sops;
        sb->s_time_gran = 1;
 
@@ -131,6 +131,7 @@ const void *kernfs_super_ns(struct super_block *sb)
  * @fs_type: file_system_type of the fs being mounted
  * @flags: mount flags specified for the mount
  * @root: kernfs_root of the hierarchy being mounted
+ * @magic: file system specific magic number
  * @new_sb_created: tell the caller if we allocated a new superblock
  * @ns: optional namespace tag of the mount
  *
@@ -142,8 +143,8 @@ const void *kernfs_super_ns(struct super_block *sb)
  * The return value can be passed to the vfs layer verbatim.
  */
 struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
-                              struct kernfs_root *root, bool *new_sb_created,
-                              const void *ns)
+                               struct kernfs_root *root, unsigned long magic,
+                               bool *new_sb_created, const void *ns)
 {
        struct super_block *sb;
        struct kernfs_super_info *info;
@@ -166,7 +167,7 @@ struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
                *new_sb_created = !sb->s_root;
 
        if (!sb->s_root) {
-               error = kernfs_fill_super(sb);
+               error = kernfs_fill_super(sb, magic);
                if (error) {
                        deactivate_locked_super(sb);
                        return ERR_PTR(error);
index e663aea..e390bd9 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 c6157c8..8016827 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 6f3f392..f66c66b 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 3ba6597..9a77a5a 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 4e565c8..732648b 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 af3f7aa..ee1f884 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 9e363e4..0855f77 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 442177b..c4b2646 100644 (file)
@@ -1351,7 +1351,7 @@ static int gather_hugetbl_stats(pte_t *pte, unsigned long hmask,
        struct numa_maps *md;
        struct page *page;
 
-       if (pte_none(*pte))
+       if (!pte_present(*pte))
                return 0;
 
        page = pte_page(*pte);
index 9bc07d2..e246954 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 28cc1ac..e9ef59b 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 a66ad61..8a49486 100644 (file)
@@ -13,6 +13,7 @@
 #define DEBUG
 
 #include <linux/fs.h>
+#include <linux/magic.h>
 #include <linux/mount.h>
 #include <linux/init.h>
 #include <linux/user_namespace.h>
@@ -38,7 +39,8 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
        }
 
        ns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
-       root = kernfs_mount_ns(fs_type, flags, sysfs_root, &new_sb, ns);
+       root = kernfs_mount_ns(fs_type, flags, sysfs_root,
+                               SYSFS_MAGIC, &new_sb, ns);
        if (IS_ERR(root) || !new_sb)
                kobj_ns_drop(KOBJ_NS_TYPE_NET, ns);
        return root;
@@ -63,7 +65,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 a126608..a81c7b5 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 01b6a01..abda112 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 fe9587f..511c283 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 01db96f..833fe5d 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 6e37823..d2e6e94 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 6e95ea7..201c609 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 1399e18..753e467 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 951a232..830c1c9 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 ef1ca01..36d6303 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 08624dc..a5f8bd9 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 993cb19..944f3d9 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 348e4d2..dc977b6 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 0c0e41b..8baf61a 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 2053767..3494eff 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 5a64ca4..f23174f 100644 (file)
@@ -93,5 +93,8 @@ static inline unsigned long virt_to_fix(const unsigned long vaddr)
 #define set_fixmap_io(idx, phys) \
        __set_fixmap(idx, phys, FIXMAP_PAGE_IO)
 
+#define set_fixmap_offset_io(idx, phys) \
+       __set_fixmap_offset(idx, phys, FIXMAP_PAGE_IO)
+
 #endif /* __ASSEMBLY__ */
 #endif /* __ASM_GENERIC_FIXMAP_H */
index b4ea8f5..5e752b9 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 d96deb4..94f9ea8 100644 (file)
@@ -50,7 +50,7 @@ static inline bool has_zero(unsigned long val, unsigned long *data, const struct
 }
 
 #ifndef zero_bytemask
-#define zero_bytemask(mask) (~0ul << __fls(mask) << 1)
+#define zero_bytemask(mask) (~1ul << __fls(mask))
 #endif
 
 #endif /* _ASM_WORD_AT_A_TIME_H */
index 49376ae..6dfd64b 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 940ece4..012d58f 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 63b5eff..fdd7e1b 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 c251585..d60904b 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 3b9bfdb..3c7ec32 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 8300fb8..72cb0dd 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 9212b01..ae9504b 100644 (file)
@@ -535,6 +535,7 @@ static inline int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_a
 extern int ftrace_arch_read_dyn_info(char *buf, int size);
 
 extern int skip_trace(unsigned long ip);
+extern void ftrace_module_init(struct module *mod);
 
 extern void ftrace_disable_daemon(void);
 extern void ftrace_enable_daemon(void);
@@ -544,6 +545,7 @@ static inline int ftrace_force_update(void) { return 0; }
 static inline void ftrace_disable_daemon(void) { }
 static inline void ftrace_enable_daemon(void) { }
 static inline void ftrace_release_mod(struct module *mod) {}
+static inline void ftrace_module_init(struct module *mod) {}
 static inline __init int register_ftrace_command(struct ftrace_func_command *cmd)
 {
        return -EINVAL;
index 5b337cf..b65166d 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 7c8b20b..a9a53b1 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 a899dc2..a6aa970 100644 (file)
@@ -194,6 +194,7 @@ struct team {
        bool user_carrier_enabled;
        bool queue_override_enabled;
        struct list_head *qom_lists; /* array of queue override mapping lists */
+       bool port_mtu_change_allowed;
        struct {
                unsigned int count;
                unsigned int interval; /* in ms */
index 13bbbde..b2acc4a 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 8834a7e..051c850 100644 (file)
@@ -210,7 +210,7 @@ extern int __irq_set_affinity(unsigned int irq, const struct cpumask *cpumask,
 /**
  * irq_set_affinity - Set the irq affinity of a given irq
  * @irq:       Interrupt to set affinity
- * @mask:      cpumask
+ * @cpumask:   cpumask
  *
  * Fails if cpumask does not contain an online CPU
  */
@@ -223,7 +223,7 @@ irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
 /**
  * irq_force_affinity - Force the irq affinity of a given irq
  * @irq:       Interrupt to set affinity
- * @mask:      cpumask
+ * @cpumask:   cpumask
  *
  * Same as irq_set_affinity, but without checking the mask against
  * online cpus.
@@ -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 10a0b1a..5c57efb 100644 (file)
@@ -603,6 +603,8 @@ static inline u32 irq_get_trigger_type(unsigned int irq)
        return d ? irqd_get_trigger_type(d) : 0;
 }
 
+unsigned int arch_dynirq_lower_bound(unsigned int from);
+
 int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
                struct module *owner);
 
index b0122dc..52bf567 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 */
@@ -280,8 +297,8 @@ void kernfs_notify(struct kernfs_node *kn);
 
 const void *kernfs_super_ns(struct super_block *sb);
 struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
-                              struct kernfs_root *root, bool *new_sb_created,
-                              const void *ns);
+                              struct kernfs_root *root, unsigned long magic,
+                              bool *new_sb_created, const void *ns);
 void kernfs_kill_sb(struct super_block *sb);
 
 void kernfs_init(void);
@@ -374,7 +391,8 @@ static inline const void *kernfs_super_ns(struct super_block *sb)
 
 static inline struct dentry *
 kernfs_mount_ns(struct file_system_type *fs_type, int flags,
-               struct kernfs_root *root, bool *new_sb_created, const void *ns)
+               struct kernfs_root *root, unsigned long magic,
+               bool *new_sb_created, const void *ns)
 { return ERR_PTR(-ENOSYS); }
 
 static inline void kernfs_kill_sb(struct super_block *sb) { }
@@ -432,9 +450,11 @@ static inline int kernfs_rename(struct kernfs_node *kn,
 
 static inline struct dentry *
 kernfs_mount(struct file_system_type *fs_type, int flags,
-            struct kernfs_root *root, bool *new_sb_created)
+               struct kernfs_root *root, unsigned long magic,
+               bool *new_sb_created)
 {
-       return kernfs_mount_ns(fs_type, flags, root, new_sb_created, NULL);
+       return kernfs_mount_ns(fs_type, flags, root,
+                               magic, new_sb_created, NULL);
 }
 
 #endif /* __LINUX_KERNFS_H */
index 34a513a..a6a42dd 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 7c36cc5..443176e 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 8d6bbd6..a383597 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 b66e761..7040dc9 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 bf9811e..d677706 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 94734a6..17d8339 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 7ed3a3a..b42d07b 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 aad8eea..034cda7 100644 (file)
@@ -16,9 +16,10 @@ static inline struct nlmsghdr *nlmsg_hdr(const struct sk_buff *skb)
 }
 
 enum netlink_skb_flags {
-       NETLINK_SKB_MMAPED      = 0x1,          /* Packet data is mmaped */
-       NETLINK_SKB_TX          = 0x2,          /* Packet was sent by userspace */
-       NETLINK_SKB_DELIVERED   = 0x4,          /* Packet was delivered */
+       NETLINK_SKB_MMAPED      = 0x1,  /* Packet data is mmaped */
+       NETLINK_SKB_TX          = 0x2,  /* Packet was sent by userspace */
+       NETLINK_SKB_DELIVERED   = 0x4,  /* Packet was delivered */
+       NETLINK_SKB_DST         = 0x8,  /* Dst set in sendto or sendmsg */
 };
 
 struct netlink_skb_parms {
@@ -169,4 +170,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 3bad8d1..e6f0988 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 3f23b44..6404253 100644 (file)
@@ -44,11 +44,16 @@ extern void of_irq_init(const struct of_device_id *matches);
 
 #ifdef CONFIG_OF_IRQ
 extern int of_irq_count(struct device_node *dev);
+extern int of_irq_get(struct device_node *dev, int index);
 #else
 static inline int of_irq_count(struct device_node *dev)
 {
        return 0;
 }
+static inline int of_irq_get(struct device_node *dev, int index)
+{
+       return 0;
+}
 #endif
 
 #if defined(CONFIG_OF)
index 6fe8464..881a7c3 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 41a13e7..7944cdc 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 95961f0..0afb48f 100644 (file)
@@ -110,7 +110,7 @@ static inline void percpu_ref_get(struct percpu_ref *ref)
        pcpu_count = ACCESS_ONCE(ref->pcpu_count);
 
        if (likely(REF_STATUS(pcpu_count) == PCPU_REF_PTR))
-               __this_cpu_inc(*pcpu_count);
+               this_cpu_inc(*pcpu_count);
        else
                atomic_inc(&ref->count);
 
@@ -139,7 +139,7 @@ static inline bool percpu_ref_tryget(struct percpu_ref *ref)
        pcpu_count = ACCESS_ONCE(ref->pcpu_count);
 
        if (likely(REF_STATUS(pcpu_count) == PCPU_REF_PTR)) {
-               __this_cpu_inc(*pcpu_count);
+               this_cpu_inc(*pcpu_count);
                ret = true;
        }
 
@@ -164,7 +164,7 @@ static inline void percpu_ref_put(struct percpu_ref *ref)
        pcpu_count = ACCESS_ONCE(ref->pcpu_count);
 
        if (likely(REF_STATUS(pcpu_count) == PCPU_REF_PTR))
-               __this_cpu_dec(*pcpu_count);
+               this_cpu_dec(*pcpu_count);
        else if (unlikely(atomic_dec_and_test(&ref->count)))
                ref->release(ref);
 
index 3356abc..3ef6ea1 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 8e3e66a..953937e 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 25f54c7..221b2bd 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 f2f7398..d82abd4 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 54f91d3..46cca4c 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 036cccd..1c3316a 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 7d64d36..4282778 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 f3539a1..f856e5a 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 6efe73c..058271b 100644 (file)
@@ -177,16 +177,9 @@ static inline void inet_peer_refcheck(const struct inet_peer *p)
 /* can be called with or without local BH being disabled */
 static inline int inet_getid(struct inet_peer *p, int more)
 {
-       int old, new;
        more++;
        inet_peer_refcheck(p);
-       do {
-               old = atomic_read(&p->ip_id_count);
-               new = old + more;
-               if (!new)
-                       new = 1;
-       } while (atomic_cmpxchg(&p->ip_id_count, old, new) != old);
-       return new;
+       return atomic_add_return(more, &p->ip_id_count) - more;
 }
 
 #endif /* _NET_INETPEER_H */
index 6c4f5ea..216cecc 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 80f500a..b2704fd 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 8338a14..21569cf 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 11fd51b..7c5cbfe 100644 (file)
@@ -25,7 +25,7 @@ struct module;
        { (1UL << TAINT_OOT_MODULE),            "O" },          \
        { (1UL << TAINT_FORCED_MODULE),         "F" },          \
        { (1UL << TAINT_CRAP),                  "C" },          \
-       { (1UL << TAINT_UNSIGNED_MODULE),       "X" })
+       { (1UL << TAINT_UNSIGNED_MODULE),       "E" })
 
 TRACE_EVENT(module_load,
 
@@ -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 f863428..c6d10af 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 6db6678..3336406 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 11917f7..4c31a36 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 cf4750e..40b5ca8 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 1ba9d62..194c1ea 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 6cb4ea8..4cc4d6e 100644 (file)
@@ -1,6 +1,7 @@
 # UAPI Header export list
 header-y += audio.h
 header-y += cdc.h
+header-y += cdc-wdm.h
 header-y += ch11.h
 header-y += ch9.h
 header-y += functionfs.h
index f03134f..0dc132e 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef _UAPI__LINUX_USB_CDC_WDM_H
 #define _UAPI__LINUX_USB_CDC_WDM_H
 
+#include <linux/types.h>
+
 /*
  * This IOCTL is used to retrieve the wMaxCommand for the device,
  * defining the message limit for both reading and writing.
index 9c7fd4c..48655ce 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 7c28936..47845c5 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 9fcdaa7..ceee0c5 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/init_task.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/magic.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
 #include <linux/mount.h>
@@ -348,7 +349,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 +1496,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 +1504,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 +1563,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;
                }
 
@@ -1604,7 +1605,8 @@ out_unlock:
        if (ret)
                return ERR_PTR(ret);
 
-       dentry = kernfs_mount(fs_type, flags, root->kf_root, &new_sb);
+       dentry = kernfs_mount(fs_type, flags, root->kf_root,
+                               CGROUP_SUPER_MAGIC, &new_sb);
        if (IS_ERR(dentry) || !new_sb)
                cgroup_put(&root->cgrp);
        return dentry;
index 2bc4a22..345628c 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 6cb20d2..019d450 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 a9e710e..247979a 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 f83a71a..440eefc 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 5f58927..de938d2 100644 (file)
@@ -743,6 +743,55 @@ void exit_pi_state_list(struct task_struct *curr)
        raw_spin_unlock_irq(&curr->pi_lock);
 }
 
+/*
+ * We need to check the following states:
+ *
+ *      Waiter | pi_state | pi->owner | uTID      | uODIED | ?
+ *
+ * [1]  NULL   | ---      | ---       | 0         | 0/1    | Valid
+ * [2]  NULL   | ---      | ---       | >0        | 0/1    | Valid
+ *
+ * [3]  Found  | NULL     | --        | Any       | 0/1    | Invalid
+ *
+ * [4]  Found  | Found    | NULL      | 0         | 1      | Valid
+ * [5]  Found  | Found    | NULL      | >0        | 1      | Invalid
+ *
+ * [6]  Found  | Found    | task      | 0         | 1      | Valid
+ *
+ * [7]  Found  | Found    | NULL      | Any       | 0      | Invalid
+ *
+ * [8]  Found  | Found    | task      | ==taskTID | 0/1    | Valid
+ * [9]  Found  | Found    | task      | 0         | 0      | Invalid
+ * [10] Found  | Found    | task      | !=taskTID | 0/1    | Invalid
+ *
+ * [1] Indicates that the kernel can acquire the futex atomically. We
+ *     came came here due to a stale FUTEX_WAITERS/FUTEX_OWNER_DIED bit.
+ *
+ * [2] Valid, if TID does not belong to a kernel thread. If no matching
+ *      thread is found then it indicates that the owner TID has died.
+ *
+ * [3] Invalid. The waiter is queued on a non PI futex
+ *
+ * [4] Valid state after exit_robust_list(), which sets the user space
+ *     value to FUTEX_WAITERS | FUTEX_OWNER_DIED.
+ *
+ * [5] The user space value got manipulated between exit_robust_list()
+ *     and exit_pi_state_list()
+ *
+ * [6] Valid state after exit_pi_state_list() which sets the new owner in
+ *     the pi_state but cannot access the user space value.
+ *
+ * [7] pi_state->owner can only be NULL when the OWNER_DIED bit is set.
+ *
+ * [8] Owner and user space value match
+ *
+ * [9] There is no transient state which sets the user space TID to 0
+ *     except exit_robust_list(), but this is indicated by the
+ *     FUTEX_OWNER_DIED bit. See [4]
+ *
+ * [10] There is no transient state which leaves owner and user space
+ *     TID out of sync.
+ */
 static int
 lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
                union futex_key *key, struct futex_pi_state **ps)
@@ -755,12 +804,13 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
        plist_for_each_entry_safe(this, next, &hb->chain, list) {
                if (match_futex(&this->key, key)) {
                        /*
-                        * Another waiter already exists - bump up
-                        * the refcount and return its pi_state:
+                        * Sanity check the waiter before increasing
+                        * the refcount and attaching to it.
                         */
                        pi_state = this->pi_state;
                        /*
-                        * Userspace might have messed up non-PI and PI futexes
+                        * Userspace might have messed up non-PI and
+                        * PI futexes [3]
                         */
                        if (unlikely(!pi_state))
                                return -EINVAL;
@@ -768,34 +818,70 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
                        WARN_ON(!atomic_read(&pi_state->refcount));
 
                        /*
-                        * When pi_state->owner is NULL then the owner died
-                        * and another waiter is on the fly. pi_state->owner
-                        * is fixed up by the task which acquires
-                        * pi_state->rt_mutex.
-                        *
-                        * We do not check for pid == 0 which can happen when
-                        * the owner died and robust_list_exit() cleared the
-                        * TID.
+                        * Handle the owner died case:
                         */
-                       if (pid && pi_state->owner) {
+                       if (uval & FUTEX_OWNER_DIED) {
+                               /*
+                                * exit_pi_state_list sets owner to NULL and
+                                * wakes the topmost waiter. The task which
+                                * acquires the pi_state->rt_mutex will fixup
+                                * owner.
+                                */
+                               if (!pi_state->owner) {
+                                       /*
+                                        * No pi state owner, but the user
+                                        * space TID is not 0. Inconsistent
+                                        * state. [5]
+                                        */
+                                       if (pid)
+                                               return -EINVAL;
+                                       /*
+                                        * Take a ref on the state and
+                                        * return. [4]
+                                        */
+                                       goto out_state;
+                               }
+
                                /*
-                                * Bail out if user space manipulated the
-                                * futex value.
+                                * If TID is 0, then either the dying owner
+                                * has not yet executed exit_pi_state_list()
+                                * or some waiter acquired the rtmutex in the
+                                * pi state, but did not yet fixup the TID in
+                                * user space.
+                                *
+                                * Take a ref on the state and return. [6]
                                 */
-                               if (pid != task_pid_vnr(pi_state->owner))
+                               if (!pid)
+                                       goto out_state;
+                       } else {
+                               /*
+                                * If the owner died bit is not set,
+                                * then the pi_state must have an
+                                * owner. [7]
+                                */
+                               if (!pi_state->owner)
                                        return -EINVAL;
                        }
 
+                       /*
+                        * Bail out if user space manipulated the
+                        * futex value. If pi state exists then the
+                        * owner TID must be the same as the user
+                        * space TID. [9/10]
+                        */
+                       if (pid != task_pid_vnr(pi_state->owner))
+                               return -EINVAL;
+
+               out_state:
                        atomic_inc(&pi_state->refcount);
                        *ps = pi_state;
-
                        return 0;
                }
        }
 
        /*
         * We are the first waiter - try to look up the real owner and attach
-        * the new pi_state to it, but bail out when TID = 0
+        * the new pi_state to it, but bail out when TID = 0 [1]
         */
        if (!pid)
                return -ESRCH;
@@ -803,6 +889,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
@@ -823,6 +914,9 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
                return ret;
        }
 
+       /*
+        * No existing pi state. First waiter. [2]
+        */
        pi_state = alloc_pi_state();
 
        /*
@@ -894,10 +988,18 @@ retry:
                return -EDEADLK;
 
        /*
-        * Surprise - we got the lock. Just return to userspace:
+        * Surprise - we got the lock, but we do not trust user space at all.
         */
-       if (unlikely(!curval))
-               return 1;
+       if (unlikely(!curval)) {
+               /*
+                * We verify whether there is kernel state for this
+                * futex. If not, we can safely assume, that the 0 ->
+                * TID transition is correct. If state exists, we do
+                * not bother to fixup the user space state as it was
+                * corrupted already.
+                */
+               return futex_top_waiter(hb, key) ? -EINVAL : 1;
+       }
 
        uval = curval;
 
@@ -1028,6 +1130,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
        struct task_struct *new_owner;
        struct futex_pi_state *pi_state = this->pi_state;
        u32 uninitialized_var(curval), newval;
+       int ret = 0;
 
        if (!pi_state)
                return -EINVAL;
@@ -1051,23 +1154,19 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
                new_owner = this->task;
 
        /*
-        * We pass it to the next owner. (The WAITERS bit is always
-        * kept enabled while there is PI state around. We must also
-        * preserve the owner died bit.)
+        * We pass it to the next owner. The WAITERS bit is always
+        * kept enabled while there is PI state around. We cleanup the
+        * owner died bit, because we are the owner.
         */
-       if (!(uval & FUTEX_OWNER_DIED)) {
-               int ret = 0;
+       newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
 
-               newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
-
-               if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
-                       ret = -EFAULT;
-               else if (curval != uval)
-                       ret = -EINVAL;
-               if (ret) {
-                       raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
-                       return ret;
-               }
+       if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
+               ret = -EFAULT;
+       else if (curval != uval)
+               ret = -EINVAL;
+       if (ret) {
+               raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
+               return ret;
        }
 
        raw_spin_lock_irq(&pi_state->owner->pi_lock);
@@ -1347,7 +1446,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 +1457,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 +1485,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,9 +1522,15 @@ 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) {
+               /*
+                * Requeue PI only works on two distinct uaddrs. This
+                * check is only valid for private futexes. See below.
+                */
+               if (uaddr1 == uaddr2)
+                       return -EINVAL;
+
                /*
                 * requeue_pi requires a pi_state, try to allocate it now
                 * without any locks in case it fails.
@@ -1462,6 +1569,15 @@ retry:
        if (unlikely(ret != 0))
                goto out_put_key1;
 
+       /*
+        * The check above which compares uaddrs is not sufficient for
+        * shared futexes. We need to compare the keys:
+        */
+       if (requeue_pi && match_futex(&key1, &key2)) {
+               ret = -EINVAL;
+               goto out_put_keys;
+       }
+
        hb1 = hash_futex(&key1);
        hb2 = hash_futex(&key2);
 
@@ -1509,16 +1625,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);
                }
 
                switch (ret) {
@@ -2301,9 +2426,10 @@ retry:
        /*
         * To avoid races, try to do the TID -> 0 atomic transition
         * again. If it succeeds then we can return without waking
-        * anyone else up:
+        * anyone else up. We only try this if neither the waiters nor
+        * the owner died bit are set.
         */
-       if (!(uval & FUTEX_OWNER_DIED) &&
+       if (!(uval & ~FUTEX_TID_MASK) &&
            cmpxchg_futex_value_locked(&uval, uaddr, vpid, 0))
                goto pi_faulted;
        /*
@@ -2333,11 +2459,9 @@ retry:
        /*
         * No waiters - kernel unlocks the futex:
         */
-       if (!(uval & FUTEX_OWNER_DIED)) {
-               ret = unlock_futex_pi(uaddr, uval);
-               if (ret == -EFAULT)
-                       goto pi_faulted;
-       }
+       ret = unlock_futex_pi(uaddr, uval);
+       if (ret == -EFAULT)
+               goto pi_faulted;
 
 out_unlock:
        spin_unlock(&hb->lock);
@@ -2499,6 +2623,15 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
        if (ret)
                goto out_key2;
 
+       /*
+        * The check above which compares uaddrs is not sufficient for
+        * shared futexes. We need to compare the keys:
+        */
+       if (match_futex(&q.key, &key2)) {
+               ret = -EINVAL;
+               goto out_put_keys;
+       }
+
        /* Queue the futex_q, drop the hb lock, wait for wakeup. */
        futex_wait_queue_me(hb, &q, to);
 
index d55092c..e0501fe 100644 (file)
@@ -234,6 +234,11 @@ again:
                        goto again;
                }
                timer->base = new_base;
+       } else {
+               if (cpu != this_cpu && hrtimer_check_target(timer, new_base)) {
+                       cpu = this_cpu;
+                       goto again;
+               }
        }
        return new_base;
 }
@@ -569,6 +574,23 @@ hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal)
 
        cpu_base->expires_next.tv64 = expires_next.tv64;
 
+       /*
+        * If a hang was detected in the last timer interrupt then we
+        * leave the hang delay active in the hardware. We want the
+        * system to make progress. That also prevents the following
+        * scenario:
+        * T1 expires 50ms from now
+        * T2 expires 5s from now
+        *
+        * T1 is removed, so this code is called and would reprogram
+        * the hardware to 5s from now. Any hrtimer_start after that
+        * will not reprogram the hardware due to hang_detected being
+        * set. So we'd effectivly block all timers until the T2 event
+        * fires.
+        */
+       if (cpu_base->hang_detected)
+               return;
+
        if (cpu_base->expires_next.tv64 != KTIME_MAX)
                tick_program_event(cpu_base->expires_next, 1);
 }
@@ -968,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
@@ -987,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 a717461..bb07f29 100644 (file)
@@ -363,6 +363,13 @@ __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
                if (from > irq)
                        return -EINVAL;
                from = irq;
+       } else {
+               /*
+                * For interrupts which are freely allocated the
+                * architecture can force a lower bound to the @from
+                * argument. x86 uses this to exclude the GSI space.
+                */
+               from = arch_dynirq_lower_bound(from);
        }
 
        mutex_lock(&sparse_irq_lock);
index c8380ad..28c5706 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 b0e9467..d24e433 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 aa4dff0..a620d4d 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 1186940..079c461 100644 (file)
@@ -815,9 +815,6 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
                return -EFAULT;
        name[MODULE_NAME_LEN-1] = '\0';
 
-       if (!(flags & O_NONBLOCK))
-               pr_warn("waiting module removal not supported: please upgrade\n");
-
        if (mutex_lock_interruptible(&module_mutex) != 0)
                return -EINTR;
 
@@ -3271,6 +3268,9 @@ static int load_module(struct load_info *info, const char __user *uargs,
 
        dynamic_debug_setup(info->debug, info->num_debug);
 
+       /* Ftrace init must be called in the MODULE_STATE_UNFORMED state */
+       ftrace_module_init(mod);
+
        /* Finally it's fully formed, ready to start executing. */
        err = complete_formation(mod, info);
        if (err)
index 18fb7a2..1ea328a 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 a45b509..7228258 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 268a45e..084d17f 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 ((int)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;
@@ -7717,8 +7751,7 @@ static int tg_set_cfs_bandwidth(struct task_group *tg, u64 period, u64 quota)
        /* restart the period timer (if active) to handle new period expiry */
        if (runtime_enabled && cfs_b->timer_active) {
                /* force a reprogram */
-               cfs_b->timer_active = 0;
-               __start_cfs_bandwidth(cfs_b);
+               __start_cfs_bandwidth(cfs_b, true);
        }
        raw_spin_unlock_irq(&cfs_b->lock);
 
index 5b9bb42..bd95963 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 a202789..538c979 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 8b836b3..8834243 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 f6d7561..6b03334 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 a95097c..72fdf06 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 b080957..14bc348 100644 (file)
@@ -513,9 +513,17 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer)
                                                     struct sched_dl_entity,
                                                     dl_timer);
        struct task_struct *p = dl_task_of(dl_se);
-       struct rq *rq = task_rq(p);
+       struct rq *rq;
+again:
+       rq = task_rq(p);
        raw_spin_lock(&rq->lock);
 
+       if (rq != task_rq(p)) {
+               /* Task was moved, retrying. */
+               raw_spin_unlock(&rq->lock);
+               goto again;
+       }
+
        /*
         * We need to take care of a possible races here. In fact, the
         * task might have changed its scheduling policy to something
@@ -528,6 +536,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 +902,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 7570dd9..8cbe2d2 100644 (file)
@@ -1707,18 +1707,19 @@ no_join:
 void task_numa_free(struct task_struct *p)
 {
        struct numa_group *grp = p->numa_group;
-       int i;
        void *numa_faults = p->numa_faults_memory;
+       unsigned long flags;
+       int i;
 
        if (grp) {
-               spin_lock_irq(&grp->lock);
+               spin_lock_irqsave(&grp->lock, flags);
                for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++)
                        grp->faults[i] -= p->numa_faults_memory[i];
                grp->total_faults -= p->total_numa_faults;
 
                list_del(&p->numa_entry);
                grp->nr_tasks--;
-               spin_unlock_irq(&grp->lock);
+               spin_unlock_irqrestore(&grp->lock, flags);
                rcu_assign_pointer(p->numa_group, NULL);
                put_numa_group(grp);
        }
@@ -3129,7 +3130,7 @@ static int assign_cfs_rq_runtime(struct cfs_rq *cfs_rq)
                 */
                if (!cfs_b->timer_active) {
                        __refill_cfs_bandwidth_runtime(cfs_b);
-                       __start_cfs_bandwidth(cfs_b);
+                       __start_cfs_bandwidth(cfs_b, false);
                }
 
                if (cfs_b->runtime > 0) {
@@ -3308,7 +3309,7 @@ static void throttle_cfs_rq(struct cfs_rq *cfs_rq)
        raw_spin_lock(&cfs_b->lock);
        list_add_tail_rcu(&cfs_rq->throttled_list, &cfs_b->throttled_cfs_rq);
        if (!cfs_b->timer_active)
-               __start_cfs_bandwidth(cfs_b);
+               __start_cfs_bandwidth(cfs_b, false);
        raw_spin_unlock(&cfs_b->lock);
 }
 
@@ -3690,7 +3691,7 @@ static void init_cfs_rq_runtime(struct cfs_rq *cfs_rq)
 }
 
 /* requires cfs_b->lock, may release to reprogram timer */
-void __start_cfs_bandwidth(struct cfs_bandwidth *cfs_b)
+void __start_cfs_bandwidth(struct cfs_bandwidth *cfs_b, bool force)
 {
        /*
         * The timer may be active because we're trying to set a new bandwidth
@@ -3705,7 +3706,7 @@ void __start_cfs_bandwidth(struct cfs_bandwidth *cfs_b)
                cpu_relax();
                raw_spin_lock(&cfs_b->lock);
                /* if someone else restarted the timer then we're done */
-               if (cfs_b->timer_active)
+               if (!force && cfs_b->timer_active)
                        return;
        }
 
@@ -6653,6 +6654,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 +6707,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 +6726,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 456e492..369b4d6 100644 (file)
@@ -278,7 +278,7 @@ extern void init_cfs_bandwidth(struct cfs_bandwidth *cfs_b);
 extern int sched_group_set_shares(struct task_group *tg, unsigned long shares);
 
 extern void __refill_cfs_bandwidth_runtime(struct cfs_bandwidth *cfs_b);
-extern void __start_cfs_bandwidth(struct cfs_bandwidth *cfs_b);
+extern void __start_cfs_bandwidth(struct cfs_bandwidth *cfs_b, bool force);
 extern void unthrottle_cfs_rq(struct cfs_rq *cfs_rq);
 
 extern void free_rt_sched_group(struct task_group *tg);
index b50990a..92f24f5 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;
@@ -779,3 +779,8 @@ int __init __weak arch_early_irq_init(void)
 {
        return 0;
 }
+
+unsigned int __weak arch_dynirq_lower_bound(unsigned int from)
+{
+       return from;
+}
index 87bd529..3bb01a3 100644 (file)
@@ -838,7 +838,7 @@ unsigned long apply_slack(struct timer_list *timer, unsigned long expires)
 
        bit = find_last_bit(&mask, BITS_PER_LONG);
 
-       mask = (1 << bit) - 1;
+       mask = (1UL << bit) - 1;
 
        expires_limit = expires_limit & ~(mask);
 
index 1fd4b94..4a54a25 100644 (file)
@@ -4330,16 +4330,11 @@ static void ftrace_init_module(struct module *mod,
        ftrace_process_locs(mod, start, end);
 }
 
-static int ftrace_module_notify_enter(struct notifier_block *self,
-                                     unsigned long val, void *data)
+void ftrace_module_init(struct module *mod)
 {
-       struct module *mod = data;
-
-       if (val == MODULE_STATE_COMING)
-               ftrace_init_module(mod, mod->ftrace_callsites,
-                                  mod->ftrace_callsites +
-                                  mod->num_ftrace_callsites);
-       return 0;
+       ftrace_init_module(mod, mod->ftrace_callsites,
+                          mod->ftrace_callsites +
+                          mod->num_ftrace_callsites);
 }
 
 static int ftrace_module_notify_exit(struct notifier_block *self,
@@ -4353,11 +4348,6 @@ static int ftrace_module_notify_exit(struct notifier_block *self,
        return 0;
 }
 #else
-static int ftrace_module_notify_enter(struct notifier_block *self,
-                                     unsigned long val, void *data)
-{
-       return 0;
-}
 static int ftrace_module_notify_exit(struct notifier_block *self,
                                     unsigned long val, void *data)
 {
@@ -4365,11 +4355,6 @@ static int ftrace_module_notify_exit(struct notifier_block *self,
 }
 #endif /* CONFIG_MODULES */
 
-struct notifier_block ftrace_module_enter_nb = {
-       .notifier_call = ftrace_module_notify_enter,
-       .priority = INT_MAX,    /* Run before anything that can use kprobes */
-};
-
 struct notifier_block ftrace_module_exit_nb = {
        .notifier_call = ftrace_module_notify_exit,
        .priority = INT_MIN,    /* Run after anything that can remove kprobes */
@@ -4403,10 +4388,6 @@ void __init ftrace_init(void)
                                  __start_mcount_loc,
                                  __stop_mcount_loc);
 
-       ret = register_module_notifier(&ftrace_module_enter_nb);
-       if (ret)
-               pr_warning("Failed to register trace ftrace module enter notifier\n");
-
        ret = register_module_notifier(&ftrace_module_exit_nb);
        if (ret)
                pr_warning("Failed to register trace ftrace module exit notifier\n");
index 925f537..4747b47 100644 (file)
@@ -77,7 +77,7 @@ event_triggers_call(struct ftrace_event_file *file, void *rec)
                        data->ops->func(data);
                        continue;
                }
-               filter = rcu_dereference(data->filter);
+               filter = rcu_dereference_sched(data->filter);
                if (filter && !filter_match_preds(filter, rec))
                        continue;
                if (data->cmd_ops->post_trigger) {
index ac5b23c..6620e58 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 0ee63af..8edc871 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 f23b63f..6745c62 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 fc67547..10ad042 100644 (file)
@@ -201,8 +201,8 @@ int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
        }
 
        if (unlikely(rem > 0))
-               printk(KERN_WARNING "netlink: %d bytes leftover after parsing "
-                      "attributes.\n", rem);
+               pr_warn_ratelimited("netlink: %d bytes leftover after parsing attributes in process `%s'.\n",
+                                   rem, current->comm);
 
        err = 0;
 errout:
index ebe5880..1b5a95f 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 37f9762..627dc2e 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 5020b28..088358c 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 2461929..c82290b 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 91d67ea..8d2fcdf 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 539eeb9..a402f8f 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 29501f0..5177c6d 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 35ef28a..9ccef39 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 78e1472..30cc47f 100644 (file)
@@ -526,9 +526,13 @@ static void queue_pages_hugetlb_pmd_range(struct vm_area_struct *vma,
        int nid;
        struct page *page;
        spinlock_t *ptl;
+       pte_t entry;
 
        ptl = huge_pte_lock(hstate_vma(vma), vma->vm_mm, (pte_t *)pmd);
-       page = pte_page(huge_ptep_get((pte_t *)pmd));
+       entry = huge_ptep_get((pte_t *)pmd);
+       if (!pte_present(entry))
+               goto unlock;
+       page = pte_page(entry);
        nid = page_to_nid(page);
        if (node_isset(nid, *nodes) == !!(flags & MPOL_MF_INVERT))
                goto unlock;
index 0843feb..05f1180 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 ef41349..a4317da 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 63e24fb..2ddf9a9 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 9c3e773..83bfafa 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1564,10 +1564,9 @@ void __put_anon_vma(struct anon_vma *anon_vma)
 {
        struct anon_vma *root = anon_vma->root;
 
+       anon_vma_free(anon_vma);
        if (root != anon_vma && atomic_dec_and_test(&root->refcount))
                anon_vma_free(root);
-
-       anon_vma_free(anon_vma);
 }
 
 static struct anon_vma *rmap_walk_anon_lock(struct page *page,
index 388cb1a..19d9218 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 3045316..6bd4c35 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 f3cfccf..102cc6f 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 5e234f1..2b1ce69 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 e5cc39a..6a78c81 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 f380af7..d5ea733 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 d4224b3..1037a3b 100644 (file)
@@ -81,10 +81,12 @@ struct vm_area_struct *vmacache_find(struct mm_struct *mm, unsigned long addr)
        for (i = 0; i < VMACACHE_SIZE; i++) {
                struct vm_area_struct *vma = current->vmacache[i];
 
-               if (vma && vma->vm_start <= addr && vma->vm_end > addr) {
-                       BUG_ON(vma->vm_mm != mm);
+               if (!vma)
+                       continue;
+               if (WARN_ON_ONCE(vma->vm_mm != mm))
+                       break;
+               if (vma->vm_start <= addr && vma->vm_end > addr)
                        return vma;
-               }
        }
 
        return NULL;
index 3f56c8d..32c661d 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 175273f..44ebd5c 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 733ec28..019efb7 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 b3bd4ec..f04224c 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 b25fd64..aa5d494 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 bcc4bea..f14e54a 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 c835e13..90cff58 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 b851cc5..fbda6b5 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 8c7ca81..96b66fd 100644 (file)
@@ -415,7 +415,7 @@ batadv_mcast_forw_ipv4_node_get(struct batadv_priv *bat_priv)
        hlist_for_each_entry_rcu(tmp_orig_node,
                                 &bat_priv->mcast.want_all_ipv4_list,
                                 mcast_want_all_ipv4_node) {
-               if (!atomic_inc_not_zero(&orig_node->refcount))
+               if (!atomic_inc_not_zero(&tmp_orig_node->refcount))
                        continue;
 
                orig_node = tmp_orig_node;
@@ -442,7 +442,7 @@ batadv_mcast_forw_ipv6_node_get(struct batadv_priv *bat_priv)
        hlist_for_each_entry_rcu(tmp_orig_node,
                                 &bat_priv->mcast.want_all_ipv6_list,
                                 mcast_want_all_ipv6_node) {
-               if (!atomic_inc_not_zero(&orig_node->refcount))
+               if (!atomic_inc_not_zero(&tmp_orig_node->refcount))
                        continue;
 
                orig_node = tmp_orig_node;
@@ -493,7 +493,7 @@ batadv_mcast_forw_unsnoop_node_get(struct batadv_priv *bat_priv)
        hlist_for_each_entry_rcu(tmp_orig_node,
                                 &bat_priv->mcast.want_all_unsnoopables_list,
                                 mcast_want_all_unsnoopables_node) {
-               if (!atomic_inc_not_zero(&orig_node->refcount))
+               if (!atomic_inc_not_zero(&tmp_orig_node->refcount))
                        continue;
 
                orig_node = tmp_orig_node;
index ffd9dfb..6a48451 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 d958e2d..521fd4f 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 4977491..15010a2 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 a1e5bb7..dc4d301 100644 (file)
@@ -7519,9 +7519,9 @@ int __init l2cap_init(void)
        l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
                                            NULL, &l2cap_debugfs_fops);
 
-       debugfs_create_u16("l2cap_le_max_credits", 0466, bt_debugfs,
+       debugfs_create_u16("l2cap_le_max_credits", 0644, bt_debugfs,
                           &le_max_credits);
-       debugfs_create_u16("l2cap_le_default_mps", 0466, bt_debugfs,
+       debugfs_create_u16("l2cap_le_default_mps", 0644, bt_debugfs,
                           &le_default_mps);
 
        bt_6lowpan_init();
index 9203d5a..474d36f 100644 (file)
@@ -487,6 +487,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
 {
        struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
        struct net_bridge_fdb_entry *fdb;
+       bool fdb_modified = false;
 
        /* some users want to always flood. */
        if (hold_time(br) == 0)
@@ -507,10 +508,15 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
                                        source->dev->name);
                } else {
                        /* fastpath: update of existing entry */
-                       fdb->dst = source;
+                       if (unlikely(source != fdb->dst)) {
+                               fdb->dst = source;
+                               fdb_modified = true;
+                       }
                        fdb->updated = jiffies;
                        if (unlikely(added_by_user))
                                fdb->added_by_user = 1;
+                       if (unlikely(fdb_modified))
+                               fdb_notify(br, fdb, RTM_NEWNEIGH);
                }
        } else {
                spin_lock(&br->hash_lock);
index 7985dea..04d6348 100644 (file)
@@ -147,8 +147,8 @@ static int br_handle_local_finish(struct sk_buff *skb)
        struct net_bridge_port *p = br_port_get_rcu(skb->dev);
        u16 vid = 0;
 
-       br_vlan_get_tag(skb, &vid);
-       if (p->flags & BR_LEARNING)
+       /* check if vlan is allowed, to avoid spoofing */
+       if (p->flags & BR_LEARNING && br_should_learn(p, skb, &vid))
                br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false);
        return 0;        /* process further */
 }
index 80e1b0f..2acf7fa 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 e74b6d5..e8844d9 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 06811d7..59d3a85 100644 (file)
@@ -581,6 +581,7 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
                        struct sk_buff *skb, u16 *vid);
 bool br_allowed_egress(struct net_bridge *br, const struct net_port_vlans *v,
                       const struct sk_buff *skb);
+bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid);
 struct sk_buff *br_handle_vlan(struct net_bridge *br,
                               const struct net_port_vlans *v,
                               struct sk_buff *skb);
@@ -648,6 +649,12 @@ static inline bool br_allowed_egress(struct net_bridge *br,
        return true;
 }
 
+static inline bool br_should_learn(struct net_bridge_port *p,
+                                  struct sk_buff *skb, u16 *vid)
+{
+       return true;
+}
+
 static inline struct sk_buff *br_handle_vlan(struct net_bridge *br,
                                             const struct net_port_vlans *v,
                                             struct sk_buff *skb)
index 4a37161..5fee2fe 100644 (file)
@@ -241,6 +241,34 @@ bool br_allowed_egress(struct net_bridge *br,
        return false;
 }
 
+/* Called under RCU */
+bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid)
+{
+       struct net_bridge *br = p->br;
+       struct net_port_vlans *v;
+
+       if (!br->vlan_enabled)
+               return true;
+
+       v = rcu_dereference(p->vlan_info);
+       if (!v)
+               return false;
+
+       br_vlan_get_tag(skb, vid);
+       if (!*vid) {
+               *vid = br_get_pvid(v);
+               if (*vid == VLAN_N_VID)
+                       return false;
+
+               return true;
+       }
+
+       if (test_bit(*vid, v->vlan_bitmap))
+               return true;
+
+       return false;
+}
+
 /* Must be protected by RTNL.
  * Must be called with vid in range from 1 to 4094 inclusive.
  */
index ac31891..050a211 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 dac7f9b..1948d59 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 e632b5a..c547e46 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 d2c8a06..fb8b054 100644 (file)
@@ -2283,8 +2283,8 @@ EXPORT_SYMBOL(skb_checksum_help);
 
 __be16 skb_network_protocol(struct sk_buff *skb, int *depth)
 {
+       unsigned int vlan_depth = skb->mac_len;
        __be16 type = skb->protocol;
-       int vlan_depth = skb->mac_len;
 
        /* Tunnel gso handlers can set protocol to ethernet. */
        if (type == htons(ETH_P_TEB)) {
@@ -2297,15 +2297,30 @@ __be16 skb_network_protocol(struct sk_buff *skb, int *depth)
                type = eth->h_proto;
        }
 
-       while (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) {
-               struct vlan_hdr *vh;
+       /* if skb->protocol is 802.1Q/AD then the header should already be
+        * present at mac_len - VLAN_HLEN (if mac_len > 0), or at
+        * ETH_HLEN otherwise
+        */
+       if (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) {
+               if (vlan_depth) {
+                       if (unlikely(WARN_ON(vlan_depth < VLAN_HLEN)))
+                               return 0;
+                       vlan_depth -= VLAN_HLEN;
+               } else {
+                       vlan_depth = ETH_HLEN;
+               }
+               do {
+                       struct vlan_hdr *vh;
 
-               if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN)))
-                       return 0;
+                       if (unlikely(!pskb_may_pull(skb,
+                                                   vlan_depth + VLAN_HLEN)))
+                               return 0;
 
-               vh = (struct vlan_hdr *)(skb->data + vlan_depth);
-               type = vh->h_vlan_encapsulated_proto;
-               vlan_depth += VLAN_HLEN;
+                       vh = (struct vlan_hdr *)(skb->data + vlan_depth);
+                       type = vh->h_vlan_encapsulated_proto;
+                       vlan_depth += VLAN_HLEN;
+               } while (type == htons(ETH_P_8021Q) ||
+                        type == htons(ETH_P_8021AD));
        }
 
        *depth = vlan_depth;
@@ -2418,7 +2433,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 +2508,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 +2545,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 +3966,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 +4556,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 +4663,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 +5139,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 +5328,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 +5632,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 cd58614..4aec7b9 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)
 {
@@ -1557,8 +1559,13 @@ static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp,
        fp->jited = 0;
 
        err = sk_chk_filter(fp->insns, fp->len);
-       if (err)
+       if (err) {
+               if (sk != NULL)
+                       sk_filter_uncharge(sk, fp);
+               else
+                       kfree(fp);
                return ERR_PTR(err);
+       }
 
        /* Probe if we can JIT compile the filter and if so, do
         * the compilation of the filter.
index 8f8a96e..32d872e 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 81d3a9a..7c8ffd9 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 d4ff417..2d8d8fc 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 1b62343..8383b2b 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 b4fff00..664ee42 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 d7af188..a4216a4 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 2f737bf..eed3433 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 5536444..f8b98d8 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 a603823..3b726f3 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 57dc159..d332aef 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 e83015c..e4d9560 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 0eb5d5e..5db37ce 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 8c54870..6d6dd34 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 8a043f0..b10cd43 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 0d1e2cb..a56b8e6 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 be8abe7..6f111e4 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 c10a3ce..ed32313 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 1cbeba5..a52f501 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 fa5b751..2acc233 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 afcee51..13ef00f 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 12e13bd..f40f321 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 8210964..044a0dd 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 db1e0da..5e676be 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 44eba05..5cde8f2 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 8bf2245..b4f1b29 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 d6b46eb..3a26b3b 100644 (file)
@@ -2684,13 +2684,12 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack)
        bool recovered = !before(tp->snd_una, tp->high_seq);
 
        if (tp->frto) { /* F-RTO RFC5682 sec 3.1 (sack enhanced version). */
-               if (flag & FLAG_ORIG_SACK_ACKED) {
-                       /* Step 3.b. A timeout is spurious if not all data are
-                        * lost, i.e., never-retransmitted data are (s)acked.
-                        */
-                       tcp_try_undo_loss(sk, true);
+               /* Step 3.b. A timeout is spurious if not all data are
+                * lost, i.e., never-retransmitted data are (s)acked.
+                */
+               if (tcp_try_undo_loss(sk, flag & FLAG_ORIG_SACK_ACKED))
                        return;
-               }
+
                if (after(tp->snd_nxt, tp->high_seq) &&
                    (flag & FLAG_DATA_SACKED || is_dupack)) {
                        tp->frto = 0; /* Loss was real: 2nd part of step 3.a */
index 025e250..12d6016 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 40e701f..186a8ec 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 7f7b243..a2ce010 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 34e0ded..87891f5 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 59f95af..b2f0915 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 40e7581..fbf1156 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 b05b609..f6a66bb 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 b7c0f82..6cc9f93 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 8659067..8250474 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 09a22f4..ca8d4ea 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 95f3f1d..d38e6a8 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 e0983f3..790e0c6 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 6313abd..56596ce 100644 (file)
@@ -12,7 +12,7 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
 {
        static atomic_t ipv6_fragmentation_id;
        struct in6_addr addr;
-       int old, new;
+       int ident;
 
 #if IS_ENABLED(CONFIG_IPV6)
        struct inet_peer *peer;
@@ -26,15 +26,10 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
                return;
        }
 #endif
-       do {
-               old = atomic_read(&ipv6_fragmentation_id);
-               new = old + 1;
-               if (!new)
-                       new = 1;
-       } while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old);
+       ident = atomic_inc_return(&ipv6_fragmentation_id);
 
        addr = rt->rt6i_dst.addr;
-       addr.s6_addr32[0] ^= (__force __be32)new;
+       addr.s6_addr32[0] ^= (__force __be32)ident;
        fhdr->identification = htonl(secure_ipv6_id(addr.s6_addr32));
 }
 EXPORT_SYMBOL(ipv6_select_ident);
index 4011617..6ebdb7b 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 0d78132..8517d3c 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 19ef329..b930d08 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 6ab989c..54d13f8 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 01e77b0..8c9d730 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 222c28b..f169b6e 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 dee50ae..27600a9 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 6fb3855..7a17dec 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 216c45b..2b608b2 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 137a192..847d92f 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 00ba90b..60cb7a6 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 a0b0aea..cec5b60 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 275c94f..3c36583 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 e9e36a2..9265adf 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 4f26ee4..3d2d2c8 100644 (file)
@@ -1392,15 +1392,19 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
 
        if (ipip) {
                __be32 info = ic->un.gateway;
+               __u8 type = ic->type;
+               __u8 code = ic->code;
 
                /* Update the MTU */
                if (ic->type == ICMP_DEST_UNREACH &&
                    ic->code == ICMP_FRAG_NEEDED) {
                        struct ip_vs_dest *dest = cp->dest;
                        u32 mtu = ntohs(ic->un.frag.mtu);
+                       __be16 frag_off = cih->frag_off;
 
                        /* Strip outer IP and ICMP, go to IPIP header */
-                       __skb_pull(skb, ihl + sizeof(_icmph));
+                       if (pskb_pull(skb, ihl + sizeof(_icmph)) == NULL)
+                               goto ignore_ipip;
                        offset2 -= ihl + sizeof(_icmph);
                        skb_reset_network_header(skb);
                        IP_VS_DBG(12, "ICMP for IPIP %pI4->%pI4: mtu=%u\n",
@@ -1408,7 +1412,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
                        ipv4_update_pmtu(skb, dev_net(skb->dev),
                                         mtu, 0, 0, 0, 0);
                        /* Client uses PMTUD? */
-                       if (!(cih->frag_off & htons(IP_DF)))
+                       if (!(frag_off & htons(IP_DF)))
                                goto ignore_ipip;
                        /* Prefer the resulting PMTU */
                        if (dest) {
@@ -1427,12 +1431,13 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
                /* Strip outer IP, ICMP and IPIP, go to IP header of
                 * original request.
                 */
-               __skb_pull(skb, offset2);
+               if (pskb_pull(skb, offset2) == NULL)
+                       goto ignore_ipip;
                skb_reset_network_header(skb);
                IP_VS_DBG(12, "Sending ICMP for %pI4->%pI4: t=%u, c=%u, i=%u\n",
                        &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr,
-                       ic->type, ic->code, ntohl(info));
-               icmp_send(skb, ic->type, ic->code, info);
+                       type, code, ntohl(info));
+               icmp_send(skb, type, code, info);
                /* ICMP can be shorter but anyways, account it */
                ip_vs_out_stats(cp, skb);
 
index ccc46fa..5857963 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 8041053..345acfb 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 e8138da..23ef77c 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 894cda0..f22757a 100644 (file)
@@ -1360,7 +1360,74 @@ 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 ((nsp->flags & NETLINK_SKB_DST) ||
+               file_ns_capable(nsp->sk->sk_socket->file, user_ns, cap)) &&
+               ns_capable(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 +1495,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 +1557,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 +2163,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)
@@ -2228,6 +2295,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
        struct sk_buff *skb;
        int err;
        struct scm_cookie scm;
+       u32 netlink_skb_flags = 0;
 
        if (msg->msg_flags&MSG_OOB)
                return -EOPNOTSUPP;
@@ -2247,8 +2315,9 @@ 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;
+               netlink_skb_flags |= NETLINK_SKB_DST;
        } else {
                dst_portid = nlk->dst_portid;
                dst_group = nlk->dst_group;
@@ -2278,6 +2347,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
        NETLINK_CB(skb).portid  = nlk->portid;
        NETLINK_CB(skb).dst_group = dst_group;
        NETLINK_CB(skb).creds   = siocb->scm->creds;
+       NETLINK_CB(skb).flags   = netlink_skb_flags;
 
        err = -EFAULT;
        if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
index b1dcdb9..a3ba3ca 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 533ce4f..92f2c71 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 dc15f43..b64151a 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 7633a75..0ad0807 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 8a5ba5a..648778a 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 29a30a1..bdbdb1a 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 eed8404..f435a88 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 a0b84e0..4007690 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 edee03d..6e957c3 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 c09757f..44cbb54 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 5d6883f..fef2acd 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 3aaf73d..ad844d3 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 5adfd94..85d232b 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 7d09a71..88f108e 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 acdcb4a..3546a77 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 8f131c1..51398ae 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 fd8fa9a..5b3add3 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 cc49062..1052d48 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 8fb1488..97130f8 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 6968992..c1827e0 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 8365909..9134dbf 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 94d0873..76cbb9e 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 6496822..1ff78ec 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 248b90a..480bbdd 100644 (file)
@@ -1059,24 +1059,26 @@ static void azx_init_cmd_io(struct azx *chip)
 
        /* reset the corb hw read pointer */
        azx_writew(chip, CORBRP, ICH6_CORBRP_RST);
-       for (timeout = 1000; timeout > 0; timeout--) {
-               if ((azx_readw(chip, CORBRP) & ICH6_CORBRP_RST) == ICH6_CORBRP_RST)
-                       break;
-               udelay(1);
-       }
-       if (timeout <= 0)
-               dev_err(chip->card->dev, "CORB reset timeout#1, CORBRP = %d\n",
-                       azx_readw(chip, CORBRP));
+       if (!(chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)) {
+               for (timeout = 1000; timeout > 0; timeout--) {
+                       if ((azx_readw(chip, CORBRP) & ICH6_CORBRP_RST) == ICH6_CORBRP_RST)
+                               break;
+                       udelay(1);
+               }
+               if (timeout <= 0)
+                       dev_err(chip->card->dev, "CORB reset timeout#1, CORBRP = %d\n",
+                               azx_readw(chip, CORBRP));
 
-       azx_writew(chip, CORBRP, 0);
-       for (timeout = 1000; timeout > 0; timeout--) {
-               if (azx_readw(chip, CORBRP) == 0)
-                       break;
-               udelay(1);
+               azx_writew(chip, CORBRP, 0);
+               for (timeout = 1000; timeout > 0; timeout--) {
+                       if (azx_readw(chip, CORBRP) == 0)
+                               break;
+                       udelay(1);
+               }
+               if (timeout <= 0)
+                       dev_err(chip->card->dev, "CORB reset timeout#2, CORBRP = %d\n",
+                               azx_readw(chip, CORBRP));
        }
-       if (timeout <= 0)
-               dev_err(chip->card->dev, "CORB reset timeout#2, CORBRP = %d\n",
-                       azx_readw(chip, CORBRP));
 
        /* enable corb dma */
        azx_writeb(chip, CORBCTL, ICH6_CORBCTL_RUN);
index d6bca62..6cc3cf2 100644 (file)
@@ -249,7 +249,8 @@ enum {
 /* quirks for Nvidia */
 #define AZX_DCAPS_PRESET_NVIDIA \
        (AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI |\
-        AZX_DCAPS_ALIGN_BUFSIZE | AZX_DCAPS_NO_64BIT)
+        AZX_DCAPS_ALIGN_BUFSIZE | AZX_DCAPS_NO_64BIT |\
+        AZX_DCAPS_CORBRP_SELF_CLEAR)
 
 #define AZX_DCAPS_PRESET_CTHDA \
        (AZX_DCAPS_NO_MSI | AZX_DCAPS_POSFIX_LPIB | AZX_DCAPS_4K_BDLE_BOUNDARY)
@@ -1366,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);
@@ -1736,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 ba38b81..4a7cb01 100644 (file)
@@ -189,6 +189,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define AZX_DCAPS_COUNT_LPIB_DELAY  (1 << 25)  /* Take LPIB as delay */
 #define AZX_DCAPS_PM_RUNTIME   (1 << 26)       /* runtime PM support */
 #define AZX_DCAPS_I915_POWERWELL (1 << 27)     /* HSW i915 powerwell support */
+#define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28)  /* CORBRP clears itself after reset */
 
 /* position fix mode */
 enum {
index 40ba06e..06275f8 100644 (file)
@@ -332,6 +332,7 @@ static const struct hda_fixup ad1986a_fixups[] = {
 
 static const struct snd_pci_quirk ad1986a_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_FIXUP_LAPTOP_IMIC),
+       SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8JN", AD1986A_FIXUP_EAPD),
        SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8100, "ASUS P5", AD1986A_FIXUP_3STACK),
        SND_PCI_QUIRK_MASK(0x1043, 0xff00, 0x8200, "ASUS M2", AD1986A_FIXUP_3STACK),
        SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_FIXUP_3STACK),
index 0cb5b89..b4218a1 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 c643dfc..d943508 100644 (file)
@@ -1647,12 +1647,10 @@ static const struct hda_fixup alc260_fixups[] = {
        [ALC260_FIXUP_COEF] = {
                .type = HDA_FIXUP_VERBS,
                .v.verbs = (const struct hda_verb[]) {
-                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
-                       { 0x20, AC_VERB_SET_PROC_COEF,  0x3040 },
+                       { 0x1a, AC_VERB_SET_COEF_INDEX, 0x07 },
+                       { 0x1a, AC_VERB_SET_PROC_COEF,  0x3040 },
                        { }
                },
-               .chained = true,
-               .chain_id = ALC260_FIXUP_HP_PIN_0F,
        },
        [ALC260_FIXUP_GPIO1] = {
                .type = HDA_FIXUP_VERBS,
@@ -1667,8 +1665,8 @@ static const struct hda_fixup alc260_fixups[] = {
        [ALC260_FIXUP_REPLACER] = {
                .type = HDA_FIXUP_VERBS,
                .v.verbs = (const struct hda_verb[]) {
-                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
-                       { 0x20, AC_VERB_SET_PROC_COEF,  0x3050 },
+                       { 0x1a, AC_VERB_SET_COEF_INDEX, 0x07 },
+                       { 0x1a, AC_VERB_SET_PROC_COEF,  0x3050 },
                        { }
                },
                .chained = true,
@@ -4616,12 +4614,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 f500905..2acf82f 100644 (file)
@@ -1018,13 +1018,13 @@ static int alc5623_i2c_probe(struct i2c_client *client,
                dev_err(&client->dev, "failed to read vendor ID1: %d\n", ret);
                return ret;
        }
-       vid1 = ((vid1 & 0xff) << 8) | (vid1 >> 8);
 
        ret = regmap_read(alc5623->regmap, ALC5623_VENDOR_ID2, &vid2);
        if (ret < 0) {
                dev_err(&client->dev, "failed to read vendor ID2: %d\n", ret);
                return ret;
        }
+       vid2 >>= 8;
 
        if ((vid1 != 0x10ec) || (vid2 != id->driver_data)) {
                dev_err(&client->dev, "unknown or wrong codec\n");
index 460d355..2213a03 100644 (file)
@@ -1229,8 +1229,10 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
        }
 
        if (cs42l52->pdata.reset_gpio) {
-               ret = gpio_request_one(cs42l52->pdata.reset_gpio,
-                                      GPIOF_OUT_INIT_HIGH, "CS42L52 /RST");
+               ret = devm_gpio_request_one(&i2c_client->dev,
+                                           cs42l52->pdata.reset_gpio,
+                                           GPIOF_OUT_INIT_HIGH,
+                                           "CS42L52 /RST");
                if (ret < 0) {
                        dev_err(&i2c_client->dev, "Failed to request /RST %d: %d\n",
                                cs42l52->pdata.reset_gpio, ret);
index 0ee60a1..ae37179 100644 (file)
@@ -1443,8 +1443,10 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
        i2c_set_clientdata(i2c_client, cs42l73);
 
        if (cs42l73->pdata.reset_gpio) {
-               ret = gpio_request_one(cs42l73->pdata.reset_gpio,
-                                      GPIOF_OUT_INIT_HIGH, "CS42L73 /RST");
+               ret = devm_gpio_request_one(&i2c_client->dev,
+                                           cs42l73->pdata.reset_gpio,
+                                           GPIOF_OUT_INIT_HIGH,
+                                           "CS42L73 /RST");
                if (ret < 0) {
                        dev_err(&i2c_client->dev, "Failed to request /RST %d: %d\n",
                                cs42l73->pdata.reset_gpio, ret);
index fa158cf..d1929de 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 b183510..d7349bc 100644 (file)
@@ -1399,7 +1399,6 @@ static int aic3x_probe(struct snd_soc_codec *codec)
        }
 
        aic3x_add_widgets(codec);
-       list_add(&aic3x->list, &reset_list);
 
        return 0;
 
@@ -1569,7 +1568,13 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_aic3x, &aic3x_dai, 1);
-       return ret;
+
+       if (ret != 0)
+               goto err_gpio;
+
+       list_add(&aic3x->list, &reset_list);
+
+       return 0;
 
 err_gpio:
        if (gpio_is_valid(aic3x->gpio_reset) &&
index 5522d25..ecd26dd 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 a1a5d52..910aafd 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 c8e5db1..496ce2e 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 b126679..605a10b 100644 (file)
@@ -144,8 +144,8 @@ enum spdif_gainsel {
 
 /* SPDIF Clock register */
 #define STC_SYSCLK_DIV_OFFSET          11
-#define STC_SYSCLK_DIV_MASK            (0x1ff << STC_TXCLK_SRC_OFFSET)
-#define STC_SYSCLK_DIV(x)              ((((x) - 1) << STC_TXCLK_DIV_OFFSET) & STC_SYSCLK_DIV_MASK)
+#define STC_SYSCLK_DIV_MASK            (0x1ff << STC_SYSCLK_DIV_OFFSET)
+#define STC_SYSCLK_DIV(x)              ((((x) - 1) << STC_SYSCLK_DIV_OFFSET) & STC_SYSCLK_DIV_MASK)
 #define STC_TXCLK_SRC_OFFSET           8
 #define STC_TXCLK_SRC_MASK             (0x7 << STC_TXCLK_SRC_OFFSET)
 #define STC_TXCLK_SRC_SET(x)           ((x << STC_TXCLK_SRC_OFFSET) & STC_TXCLK_SRC_MASK)
index ac86993..267717a 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 5d06eec..18aee77 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 a50bf7f..adf0aca 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 d0eaeee..0d31dbb 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 fe8e81a..4012134 100644 (file)
@@ -136,7 +136,7 @@ struct sst_module_data {
        enum sst_data_type data_type;   /* type of module data */
 
        u32 size;               /* size in bytes */
-       u32 offset;             /* offset in FW file */
+       int32_t offset;         /* offset in FW file */
        u32 data_offset;        /* offset in ADSP memory space */
        void *data;             /* module data */
 };
@@ -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 0c129fd..0b715b2 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 74052b5..e44423b 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 f768710..928f228 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 f5ebf36..535f517 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 f46bb4d..e7996b3 100644 (file)
@@ -617,7 +617,7 @@ static void hsw_notification_work(struct work_struct *work)
        case IPC_POSITION_CHANGED:
                trace_ipc_notification("DSP stream position changed for",
                        stream->reply.stream_hw_id);
-               sst_dsp_inbox_read(hsw->dsp, pos, sizeof(pos));
+               sst_dsp_inbox_read(hsw->dsp, pos, sizeof(*pos));
 
                if (stream->notify_position)
                        stream->notify_position(stream, stream->pdata);
@@ -991,7 +991,8 @@ int sst_hsw_stream_get_volume(struct sst_hsw *hsw, struct sst_hsw_stream *stream
                return -EINVAL;
 
        sst_dsp_read(hsw->dsp, volume,
-               stream->reply.volume_register_address[channel], sizeof(volume));
+               stream->reply.volume_register_address[channel],
+               sizeof(*volume));
 
        return 0;
 }
@@ -1158,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;
@@ -1171,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;
 }
@@ -1179,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)
@@ -1200,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;
 }
@@ -1537,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,
@@ -1609,7 +1637,7 @@ int sst_hsw_dx_set_state(struct sst_hsw *hsw,
        trace_ipc_request("PM enter Dx state", state);
 
        ret = ipc_tx_message_wait(hsw, header, &state_, sizeof(state_),
-               dx, sizeof(dx));
+               dx, sizeof(*dx));
        if (ret < 0) {
                dev_err(hsw->dev, "ipc: error set dx state %d failed\n", state);
                return ret;
index d517929..2ac194a 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 0a32dd1..9d5f64a 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 be873c1..d32c540 100644 (file)
@@ -1,10 +1,8 @@
 #
 # Jz4740 Platform Support
 #
-snd-soc-jz4740-objs := jz4740-pcm.o
 snd-soc-jz4740-i2s-objs := jz4740-i2s.o
 
-obj-$(CONFIG_SND_JZ4740_SOC) += snd-soc-jz4740.o
 obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o
 
 # Jz4740 Machine Support
index 215b668..8942447 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 6232b7d..4d0720e 100644 (file)
@@ -258,7 +258,7 @@ static int rsnd_src_init(struct rsnd_mod *mod,
 {
        struct rsnd_src *src = rsnd_mod_to_src(mod);
 
-       clk_enable(src->clk);
+       clk_prepare_enable(src->clk);
 
        return 0;
 }
@@ -269,7 +269,7 @@ static int rsnd_src_quit(struct rsnd_mod *mod,
 {
        struct rsnd_src *src = rsnd_mod_to_src(mod);
 
-       clk_disable(src->clk);
+       clk_disable_unprepare(src->clk);
 
        return 0;
 }
index 4b7e206..1d8387c 100644 (file)
@@ -171,7 +171,7 @@ static void rsnd_ssi_hw_start(struct rsnd_ssi *ssi,
        u32 cr;
 
        if (0 == ssi->usrcnt) {
-               clk_enable(ssi->clk);
+               clk_prepare_enable(ssi->clk);
 
                if (rsnd_dai_is_clk_master(rdai)) {
                        if (rsnd_ssi_clk_from_parent(ssi))
@@ -230,7 +230,7 @@ static void rsnd_ssi_hw_stop(struct rsnd_ssi *ssi,
                                rsnd_ssi_master_clk_stop(ssi);
                }
 
-               clk_disable(ssi->clk);
+               clk_disable_unprepare(ssi->clk);
        }
 
        dev_dbg(dev, "ssi%d hw stopped\n", rsnd_mod_id(&ssi->mod));
index c8a780d..6d6ceee 100644 (file)
@@ -254,7 +254,6 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
 static void dapm_kcontrol_free(struct snd_kcontrol *kctl)
 {
        struct dapm_kcontrol_data *data = snd_kcontrol_chip(kctl);
-       kfree(data->widget);
        kfree(data->wlist);
        kfree(data);
 }
@@ -1613,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,
@@ -3476,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 2cedf09..a391de0 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 893d5a1..c3b5b7d 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 9867ab8..97acb90 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 e70a87e..289f582 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 131336d..c62a165 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 25c4c7e..91d0380 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 bcae806..9a617ad 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 7c43479..a74fba6 100644 (file)
@@ -12,8 +12,8 @@
 char debugfs_mountpoint[PATH_MAX + 1] = "/sys/kernel/debug";
 
 static const char * const debugfs_known_mountpoints[] = {
-       "/sys/kernel/debug/",
-       "/debug/",
+       "/sys/kernel/debug",
+       "/debug",
        0,
 };
 
index cb09d3f..bba2f52 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 baec7d8..b83184f 100644 (file)
@@ -4344,6 +4344,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
                                              format, len_arg, arg);
                                trace_seq_terminate(&p);
                                trace_seq_puts(s, p.buffer);
+                               trace_seq_destroy(&p);
                                arg = arg->next;
                                break;
                        default:
index 791c539..feab942 100644 (file)
@@ -876,8 +876,8 @@ struct event_filter {
 struct event_filter *pevent_filter_alloc(struct pevent *pevent);
 
 /* for backward compatibility */
-#define FILTER_NONE            PEVENT_ERRNO__FILTER_NOT_FOUND
-#define FILTER_NOEXIST         PEVENT_ERRNO__NO_FILTER
+#define FILTER_NONE            PEVENT_ERRNO__NO_FILTER
+#define FILTER_NOEXIST         PEVENT_ERRNO__FILTER_NOT_FOUND
 #define FILTER_MISS            PEVENT_ERRNO__FILTER_MISS
 #define FILTER_MATCH           PEVENT_ERRNO__FILTER_MATCH
 
index bb31813..9a287be 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;
index e969233..895edd3 100644 (file)
@@ -589,7 +589,7 @@ $(GTK_OBJS): $(OUTPUT)%.o: %.c $(LIB_H)
        $(QUIET_CC)$(CC) -o $@ -c -fPIC $(CFLAGS) $(GTK_CFLAGS) $<
 
 $(OUTPUT)libperf-gtk.so: $(GTK_OBJS) $(PERFLIBS)
-       $(QUIET_LINK)$(CC) -o $@ -shared $(ALL_LDFLAGS) $(filter %.o,$^) $(GTK_LIBS)
+       $(QUIET_LINK)$(CC) -o $@ -shared $(LDFLAGS) $(filter %.o,$^) $(GTK_LIBS)
 
 $(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
        $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
index b602ad9..83bc238 100644 (file)
@@ -23,9 +23,10 @@ static int sample_ustack(struct perf_sample *sample,
 
        sp = (unsigned long) regs[PERF_REG_X86_SP];
 
-       map = map_groups__find(&thread->mg, MAP__FUNCTION, (u64) sp);
+       map = map_groups__find(&thread->mg, MAP__VARIABLE, (u64) sp);
        if (!map) {
                pr_debug("failed to get stack map\n");
+               free(buf);
                return -1;
        }
 
index 99167bf..60875d5 100644 (file)
@@ -1,4 +1,3 @@
-
 #include <linux/linkage.h>
 
 #define AX      0
@@ -90,3 +89,10 @@ ENTRY(perf_regs_load)
        ret
 ENDPROC(perf_regs_load)
 #endif
+
+/*
+ * We need to provide note.GNU-stack section, saying that we want
+ * NOT executable stack. Otherwise the final linking will assume that
+ * the ELF stack should not be restricted at all and set it RWX.
+ */
+.section .note.GNU-stack,"",@progbits
index ee21fa9..802cf54 100644 (file)
@@ -34,6 +34,14 @@ ifeq ($(ARCH),arm)
   LIBUNWIND_LIBS = -lunwind -lunwind-arm
 endif
 
+# So far there's only x86 libdw unwind support merged in perf.
+# Disable it on all other architectures in case libdw unwind
+# support is detected in system. Add supported architectures
+# to the check.
+ifneq ($(ARCH),x86)
+  NO_LIBDW_DWARF_UNWIND := 1
+endif
+
 ifeq ($(LIBUNWIND_LIBS),)
   NO_LIBUNWIND := 1
 else
@@ -109,6 +117,10 @@ CFLAGS += -Wall
 CFLAGS += -Wextra
 CFLAGS += -std=gnu99
 
+# Enforce a non-executable stack, as we may regress (again) in the future by
+# adding assembler files missing the .GNU-stack linker note.
+LDFLAGS += -Wl,-z,noexecstack
+
 EXTLIBS = -lelf -lpthread -lrt -lm -ldl
 
 ifneq ($(OUTPUT),)
@@ -186,7 +198,10 @@ VF_FEATURE_TESTS =                 \
        stackprotector-all              \
        timerfd                         \
        libunwind-debug-frame           \
-       bionic
+       bionic                          \
+       liberty                         \
+       liberty-z                       \
+       cplus-demangle
 
 # Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features.
 # If in the future we need per-feature checks/flags for features not
@@ -504,7 +519,21 @@ else
 endif
 
 ifeq ($(feature-libbfd), 1)
-  EXTLIBS += -lbfd -lz -liberty
+  EXTLIBS += -lbfd
+
+  # call all detections now so we get correct
+  # status in VF output
+  $(call feature_check,liberty)
+  $(call feature_check,liberty-z)
+  $(call feature_check,cplus-demangle)
+
+  ifeq ($(feature-liberty), 1)
+    EXTLIBS += -liberty
+  else
+    ifeq ($(feature-liberty-z), 1)
+      EXTLIBS += -liberty -lz
+    endif
+  endif
 endif
 
 ifdef NO_DEMANGLE
@@ -515,15 +544,10 @@ else
     CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
   else
     ifneq ($(feature-libbfd), 1)
-      $(call feature_check,liberty)
-      ifeq ($(feature-liberty), 1)
-        EXTLIBS += -lbfd -liberty
-      else
-        $(call feature_check,liberty-z)
-        ifeq ($(feature-liberty-z), 1)
-          EXTLIBS += -lbfd -liberty -lz
-        else
-          $(call feature_check,cplus-demangle)
+      ifneq ($(feature-liberty), 1)
+        ifneq ($(feature-liberty-z), 1)
+          # we dont have neither HAVE_CPLUS_DEMANGLE_SUPPORT
+          # or any of 'bfd iberty z' trinity
           ifeq ($(feature-cplus-demangle), 1)
             EXTLIBS += -liberty
             CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
index 5daeae1..2f92d6e 100644 (file)
@@ -46,6 +46,7 @@ make_install_man    := install-man
 make_install_html   := install-html
 make_install_info   := install-info
 make_install_pdf    := install-pdf
+make_static         := LDFLAGS=-static
 
 # all the NO_* variable combined
 make_minimal        := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
@@ -87,6 +88,7 @@ run += make_install_bin
 # run += make_install_info
 # run += make_install_pdf
 run += make_minimal
+run += make_static
 
 ifneq ($(call has,ctags),)
 run += make_tags
index 7defd77..cc66c40 100644 (file)
@@ -747,14 +747,17 @@ struct __find_variable_param {
 static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
 {
        struct __find_variable_param *fvp = data;
+       Dwarf_Attribute attr;
        int tag;
 
        tag = dwarf_tag(die_mem);
        if ((tag == DW_TAG_formal_parameter ||
             tag == DW_TAG_variable) &&
-           die_compare_name(die_mem, fvp->name))
+           die_compare_name(die_mem, fvp->name) &&
+       /* Does the DIE have location information or external instance? */
+           (dwarf_attr(die_mem, DW_AT_external, &attr) ||
+            dwarf_attr(die_mem, DW_AT_location, &attr)))
                return DIE_FIND_CB_END;
-
        if (dwarf_haspc(die_mem, fvp->addr))
                return DIE_FIND_CB_CONTINUE;
        else
index a53cd0b..27c2a5e 100644 (file)
@@ -717,7 +717,7 @@ static char *get_kernel_version(const char *root_dir)
 }
 
 static int map_groups__set_modules_path_dir(struct map_groups *mg,
-                               const char *dir_name)
+                               const char *dir_name, int depth)
 {
        struct dirent *dent;
        DIR *dir = opendir(dir_name);
@@ -742,7 +742,15 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
                            !strcmp(dent->d_name, ".."))
                                continue;
 
-                       ret = map_groups__set_modules_path_dir(mg, path);
+                       /* Do not follow top-level source and build symlinks */
+                       if (depth == 0) {
+                               if (!strcmp(dent->d_name, "source") ||
+                                   !strcmp(dent->d_name, "build"))
+                                       continue;
+                       }
+
+                       ret = map_groups__set_modules_path_dir(mg, path,
+                                                              depth + 1);
                        if (ret < 0)
                                goto out;
                } else {
@@ -786,11 +794,11 @@ static int machine__set_modules_path(struct machine *machine)
        if (!version)
                return -1;
 
-       snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel",
+       snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s",
                 machine->root_dir, version);
        free(version);
 
-       return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);
+       return map_groups__set_modules_path_dir(&machine->kmaps, modules_path, 0);
 }
 
 static int machine__create_module(void *arg, const char *name, u64 start)
index 5627621..9d8eb26 100644 (file)
@@ -511,12 +511,12 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
 
        ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
                                        &pf->sp_die, pf->tvar);
-       if (ret == -ENOENT)
+       if (ret == -ENOENT || ret == -EINVAL)
                pr_err("Failed to find the location of %s at this address.\n"
                       " Perhaps, it has been optimized out.\n", pf->pvar->var);
        else if (ret == -ENOTSUP)
                pr_err("Sorry, we don't support this variable location yet.\n");
-       else if (pf->pvar->field) {
+       else if (ret == 0 && pf->pvar->field) {
                ret = convert_variable_fields(vr_die, pf->pvar->var,
                                              pf->pvar->field, &pf->tvar->ref,
                                              &die_mem);
index 47b2983..56ff9be 100644 (file)
@@ -548,11 +548,10 @@ static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu,
        u32 val;
        u32 *reg;
 
-       offset >>= 1;
        reg = vgic_bitmap_get_reg(&vcpu->kvm->arch.vgic.irq_cfg,
-                                 vcpu->vcpu_id, offset);
+                                 vcpu->vcpu_id, offset >> 1);
 
-       if (offset & 2)
+       if (offset & 4)
                val = *reg >> 16;
        else
                val = *reg & 0xffff;
@@ -561,13 +560,13 @@ static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu,
        vgic_reg_access(mmio, &val, offset,
                        ACCESS_READ_VALUE | ACCESS_WRITE_VALUE);
        if (mmio->is_write) {
-               if (offset < 4) {
+               if (offset < 8) {
                        *reg = ~0U; /* Force PPIs/SGIs to 1 */
                        return false;
                }
 
                val = vgic_cfg_compress(val);
-               if (offset & 2) {
+               if (offset & 4) {
                        *reg &= 0xffff;
                        *reg |= val << 16;
                } else {
@@ -916,6 +915,7 @@ static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg)
        case 0:
                if (!target_cpus)
                        return;
+               break;
 
        case 1:
                target_cpus = ((1 << nrcpus) - 1) & ~(1 << vcpu_id) & 0xff;
@@ -1667,10 +1667,11 @@ static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr,
        if (addr + size < addr)
                return -EINVAL;
 
+       *ioaddr = addr;
        ret = vgic_ioaddr_overlap(kvm);
        if (ret)
-               return ret;
-       *ioaddr = addr;
+               *ioaddr = VGIC_ADDR_UNDEF;
+
        return ret;
 }
 
index 8db4370..bf06577 100644 (file)
@@ -395,7 +395,8 @@ static int assigned_device_enable_host_msix(struct kvm *kvm,
        if (dev->entries_nr == 0)
                return r;
 
-       r = pci_enable_msix(dev->dev, dev->host_msix_entries, dev->entries_nr);
+       r = pci_enable_msix_exact(dev->dev,
+                                 dev->host_msix_entries, dev->entries_nr);
        if (r)
                return r;
 
index 10df100..06e6401 100644 (file)
@@ -101,7 +101,7 @@ static void async_pf_execute(struct work_struct *work)
        if (waitqueue_active(&vcpu->wq))
                wake_up_interruptible(&vcpu->wq);
 
-       mmdrop(mm);
+       mmput(mm);
        kvm_put_kvm(vcpu->kvm);
 }
 
@@ -118,7 +118,7 @@ void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu)
                flush_work(&work->work);
 #else
                if (cancel_work_sync(&work->work)) {
-                       mmdrop(work->mm);
+                       mmput(work->mm);
                        kvm_put_kvm(vcpu->kvm); /* == work->vcpu->kvm */
                        kmem_cache_free(async_pf_cache, work);
                }
@@ -183,7 +183,7 @@ int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, unsigned long hva,
        work->addr = hva;
        work->arch = *arch;
        work->mm = current->mm;
-       atomic_inc(&work->mm->mm_count);
+       atomic_inc(&work->mm->mm_users);
        kvm_get_kvm(work->vcpu->kvm);
 
        /* this can't really happen otherwise gfn_to_pfn_async
@@ -201,7 +201,7 @@ int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, unsigned long hva,
        return 1;
 retry_sync:
        kvm_put_kvm(work->vcpu->kvm);
-       mmdrop(work->mm);
+       mmput(work->mm);
        kmem_cache_free(async_pf_cache, work);
        return 0;
 }